##// END OF EJS Templates
Do a redirect when accessing a renamed wiki page....
Jean-Philippe Lang -
r5303:3cc7353093a7
parent child
Show More
@@ -1,275 +1,284
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2011 Jean-Philippe Lang
2 # Copyright (C) 2006-2011 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 'diff'
18 require 'diff'
19
19
20 # The WikiController follows the Rails REST controller pattern but with
20 # The WikiController follows the Rails REST controller pattern but with
21 # a few differences
21 # a few differences
22 #
22 #
23 # * index - shows a list of WikiPages grouped by page or date
23 # * index - shows a list of WikiPages grouped by page or date
24 # * new - not used
24 # * new - not used
25 # * create - not used
25 # * create - not used
26 # * show - will also show the form for creating a new wiki page
26 # * show - will also show the form for creating a new wiki page
27 # * edit - used to edit an existing or new page
27 # * edit - used to edit an existing or new page
28 # * update - used to save a wiki page update to the database, including new pages
28 # * update - used to save a wiki page update to the database, including new pages
29 # * destroy - normal
29 # * destroy - normal
30 #
30 #
31 # Other member and collection methods are also used
31 # Other member and collection methods are also used
32 #
32 #
33 # TODO: still being worked on
33 # TODO: still being worked on
34 class WikiController < ApplicationController
34 class WikiController < ApplicationController
35 default_search_scope :wiki_pages
35 default_search_scope :wiki_pages
36 before_filter :find_wiki, :authorize
36 before_filter :find_wiki, :authorize
37 before_filter :find_existing_or_new_page, :only => [:show, :edit, :update]
37 before_filter :find_existing_or_new_page, :only => [:show, :edit, :update]
38 before_filter :find_existing_page, :only => [:rename, :protect, :history, :diff, :annotate, :add_attachment, :destroy]
38 before_filter :find_existing_page, :only => [:rename, :protect, :history, :diff, :annotate, :add_attachment, :destroy]
39
39
40 helper :attachments
40 helper :attachments
41 include AttachmentsHelper
41 include AttachmentsHelper
42 helper :watchers
42 helper :watchers
43
43
44 # List of pages, sorted alphabetically and by parent (hierarchy)
44 # List of pages, sorted alphabetically and by parent (hierarchy)
45 def index
45 def index
46 load_pages_for_index
46 load_pages_for_index
47 @pages_by_parent_id = @pages.group_by(&:parent_id)
47 @pages_by_parent_id = @pages.group_by(&:parent_id)
48 end
48 end
49
49
50 # List of page, by last update
50 # List of page, by last update
51 def date_index
51 def date_index
52 load_pages_for_index
52 load_pages_for_index
53 @pages_by_date = @pages.group_by {|p| p.updated_on.to_date}
53 @pages_by_date = @pages.group_by {|p| p.updated_on.to_date}
54 end
54 end
55
55
56 # display a page (in editing mode if it doesn't exist)
56 # display a page (in editing mode if it doesn't exist)
57 def show
57 def show
58 if @page.new_record?
58 if @page.new_record?
59 if User.current.allowed_to?(:edit_wiki_pages, @project) && editable?
59 if User.current.allowed_to?(:edit_wiki_pages, @project) && editable?
60 edit
60 edit
61 render :action => 'edit'
61 render :action => 'edit'
62 else
62 else
63 render_404
63 render_404
64 end
64 end
65 return
65 return
66 end
66 end
67 if params[:version] && !User.current.allowed_to?(:view_wiki_edits, @project)
67 if params[:version] && !User.current.allowed_to?(:view_wiki_edits, @project)
68 # Redirects user to the current version if he's not allowed to view previous versions
68 # Redirects user to the current version if he's not allowed to view previous versions
69 redirect_to :version => nil
69 redirect_to :version => nil
70 return
70 return
71 end
71 end
72 @content = @page.content_for_version(params[:version])
72 @content = @page.content_for_version(params[:version])
73 if User.current.allowed_to?(:export_wiki_pages, @project)
73 if User.current.allowed_to?(:export_wiki_pages, @project)
74 if params[:format] == 'html'
74 if params[:format] == 'html'
75 export = render_to_string :action => 'export', :layout => false
75 export = render_to_string :action => 'export', :layout => false
76 send_data(export, :type => 'text/html', :filename => "#{@page.title}.html")
76 send_data(export, :type => 'text/html', :filename => "#{@page.title}.html")
77 return
77 return
78 elsif params[:format] == 'txt'
78 elsif params[:format] == 'txt'
79 send_data(@content.text, :type => 'text/plain', :filename => "#{@page.title}.txt")
79 send_data(@content.text, :type => 'text/plain', :filename => "#{@page.title}.txt")
80 return
80 return
81 end
81 end
82 end
82 end
83 @editable = editable?
83 @editable = editable?
84 render :action => 'show'
84 render :action => 'show'
85 end
85 end
86
86
87 # edit an existing page or a new one
87 # edit an existing page or a new one
88 def edit
88 def edit
89 return render_403 unless editable?
89 return render_403 unless editable?
90 @page.content = WikiContent.new(:page => @page) if @page.new_record?
90 @page.content = WikiContent.new(:page => @page) if @page.new_record?
91
91
92 @content = @page.content_for_version(params[:version])
92 @content = @page.content_for_version(params[:version])
93 @content.text = initial_page_content(@page) if @content.text.blank?
93 @content.text = initial_page_content(@page) if @content.text.blank?
94 # don't keep previous comment
94 # don't keep previous comment
95 @content.comments = nil
95 @content.comments = nil
96
96
97 # To prevent StaleObjectError exception when reverting to a previous version
97 # To prevent StaleObjectError exception when reverting to a previous version
98 @content.version = @page.content.version
98 @content.version = @page.content.version
99 end
99 end
100
100
101 verify :method => :put, :only => :update, :render => {:nothing => true, :status => :method_not_allowed }
101 verify :method => :put, :only => :update, :render => {:nothing => true, :status => :method_not_allowed }
102 # Creates a new page or updates an existing one
102 # Creates a new page or updates an existing one
103 def update
103 def update
104 return render_403 unless editable?
104 return render_403 unless editable?
105 @page.content = WikiContent.new(:page => @page) if @page.new_record?
105 @page.content = WikiContent.new(:page => @page) if @page.new_record?
106
106
107 @content = @page.content_for_version(params[:version])
107 @content = @page.content_for_version(params[:version])
108 @content.text = initial_page_content(@page) if @content.text.blank?
108 @content.text = initial_page_content(@page) if @content.text.blank?
109 # don't keep previous comment
109 # don't keep previous comment
110 @content.comments = nil
110 @content.comments = nil
111
111
112 if !@page.new_record? && params[:content].present? && @content.text == params[:content][:text]
112 if !@page.new_record? && params[:content].present? && @content.text == params[:content][:text]
113 attachments = Attachment.attach_files(@page, params[:attachments])
113 attachments = Attachment.attach_files(@page, params[:attachments])
114 render_attachment_warning_if_needed(@page)
114 render_attachment_warning_if_needed(@page)
115 # don't save if text wasn't changed
115 # don't save if text wasn't changed
116 redirect_to :action => 'show', :project_id => @project, :id => @page.title
116 redirect_to :action => 'show', :project_id => @project, :id => @page.title
117 return
117 return
118 end
118 end
119 @content.attributes = params[:content]
119 @content.attributes = params[:content]
120 @content.author = User.current
120 @content.author = User.current
121 # if page is new @page.save will also save content, but not if page isn't a new record
121 # if page is new @page.save will also save content, but not if page isn't a new record
122 if (@page.new_record? ? @page.save : @content.save)
122 if (@page.new_record? ? @page.save : @content.save)
123 attachments = Attachment.attach_files(@page, params[:attachments])
123 attachments = Attachment.attach_files(@page, params[:attachments])
124 render_attachment_warning_if_needed(@page)
124 render_attachment_warning_if_needed(@page)
125 call_hook(:controller_wiki_edit_after_save, { :params => params, :page => @page})
125 call_hook(:controller_wiki_edit_after_save, { :params => params, :page => @page})
126 redirect_to :action => 'show', :project_id => @project, :id => @page.title
126 redirect_to :action => 'show', :project_id => @project, :id => @page.title
127 else
127 else
128 render :action => 'edit'
128 render :action => 'edit'
129 end
129 end
130
130
131 rescue ActiveRecord::StaleObjectError
131 rescue ActiveRecord::StaleObjectError
132 # Optimistic locking exception
132 # Optimistic locking exception
133 flash.now[:error] = l(:notice_locking_conflict)
133 flash.now[:error] = l(:notice_locking_conflict)
134 render :action => 'edit'
134 render :action => 'edit'
135 end
135 end
136
136
137 # rename a page
137 # rename a page
138 def rename
138 def rename
139 return render_403 unless editable?
139 return render_403 unless editable?
140 @page.redirect_existing_links = true
140 @page.redirect_existing_links = true
141 # used to display the *original* title if some AR validation errors occur
141 # used to display the *original* title if some AR validation errors occur
142 @original_title = @page.pretty_title
142 @original_title = @page.pretty_title
143 if request.post? && @page.update_attributes(params[:wiki_page])
143 if request.post? && @page.update_attributes(params[:wiki_page])
144 flash[:notice] = l(:notice_successful_update)
144 flash[:notice] = l(:notice_successful_update)
145 redirect_to :action => 'show', :project_id => @project, :id => @page.title
145 redirect_to :action => 'show', :project_id => @project, :id => @page.title
146 end
146 end
147 end
147 end
148
148
149 verify :method => :post, :only => :protect, :redirect_to => { :action => :show }
149 verify :method => :post, :only => :protect, :redirect_to => { :action => :show }
150 def protect
150 def protect
151 @page.update_attribute :protected, params[:protected]
151 @page.update_attribute :protected, params[:protected]
152 redirect_to :action => 'show', :project_id => @project, :id => @page.title
152 redirect_to :action => 'show', :project_id => @project, :id => @page.title
153 end
153 end
154
154
155 # show page history
155 # show page history
156 def history
156 def history
157 @version_count = @page.content.versions.count
157 @version_count = @page.content.versions.count
158 @version_pages = Paginator.new self, @version_count, per_page_option, params['p']
158 @version_pages = Paginator.new self, @version_count, per_page_option, params['p']
159 # don't load text
159 # don't load text
160 @versions = @page.content.versions.find :all,
160 @versions = @page.content.versions.find :all,
161 :select => "id, author_id, comments, updated_on, version",
161 :select => "id, author_id, comments, updated_on, version",
162 :order => 'version DESC',
162 :order => 'version DESC',
163 :limit => @version_pages.items_per_page + 1,
163 :limit => @version_pages.items_per_page + 1,
164 :offset => @version_pages.current.offset
164 :offset => @version_pages.current.offset
165
165
166 render :layout => false if request.xhr?
166 render :layout => false if request.xhr?
167 end
167 end
168
168
169 def diff
169 def diff
170 @diff = @page.diff(params[:version], params[:version_from])
170 @diff = @page.diff(params[:version], params[:version_from])
171 render_404 unless @diff
171 render_404 unless @diff
172 end
172 end
173
173
174 def annotate
174 def annotate
175 @annotate = @page.annotate(params[:version])
175 @annotate = @page.annotate(params[:version])
176 render_404 unless @annotate
176 render_404 unless @annotate
177 end
177 end
178
178
179 verify :method => :delete, :only => [:destroy], :redirect_to => { :action => :show }
179 verify :method => :delete, :only => [:destroy], :redirect_to => { :action => :show }
180 # Removes a wiki page and its history
180 # Removes a wiki page and its history
181 # Children can be either set as root pages, removed or reassigned to another parent page
181 # Children can be either set as root pages, removed or reassigned to another parent page
182 def destroy
182 def destroy
183 return render_403 unless editable?
183 return render_403 unless editable?
184
184
185 @descendants_count = @page.descendants.size
185 @descendants_count = @page.descendants.size
186 if @descendants_count > 0
186 if @descendants_count > 0
187 case params[:todo]
187 case params[:todo]
188 when 'nullify'
188 when 'nullify'
189 # Nothing to do
189 # Nothing to do
190 when 'destroy'
190 when 'destroy'
191 # Removes all its descendants
191 # Removes all its descendants
192 @page.descendants.each(&:destroy)
192 @page.descendants.each(&:destroy)
193 when 'reassign'
193 when 'reassign'
194 # Reassign children to another parent page
194 # Reassign children to another parent page
195 reassign_to = @wiki.pages.find_by_id(params[:reassign_to_id].to_i)
195 reassign_to = @wiki.pages.find_by_id(params[:reassign_to_id].to_i)
196 return unless reassign_to
196 return unless reassign_to
197 @page.children.each do |child|
197 @page.children.each do |child|
198 child.update_attribute(:parent, reassign_to)
198 child.update_attribute(:parent, reassign_to)
199 end
199 end
200 else
200 else
201 @reassignable_to = @wiki.pages - @page.self_and_descendants
201 @reassignable_to = @wiki.pages - @page.self_and_descendants
202 return
202 return
203 end
203 end
204 end
204 end
205 @page.destroy
205 @page.destroy
206 redirect_to :action => 'index', :project_id => @project
206 redirect_to :action => 'index', :project_id => @project
207 end
207 end
208
208
209 # Export wiki to a single html file
209 # Export wiki to a single html file
210 def export
210 def export
211 if User.current.allowed_to?(:export_wiki_pages, @project)
211 if User.current.allowed_to?(:export_wiki_pages, @project)
212 @pages = @wiki.pages.find :all, :order => 'title'
212 @pages = @wiki.pages.find :all, :order => 'title'
213 export = render_to_string :action => 'export_multiple', :layout => false
213 export = render_to_string :action => 'export_multiple', :layout => false
214 send_data(export, :type => 'text/html', :filename => "wiki.html")
214 send_data(export, :type => 'text/html', :filename => "wiki.html")
215 else
215 else
216 redirect_to :action => 'show', :project_id => @project, :id => nil
216 redirect_to :action => 'show', :project_id => @project, :id => nil
217 end
217 end
218 end
218 end
219
219
220 def preview
220 def preview
221 page = @wiki.find_page(params[:id])
221 page = @wiki.find_page(params[:id])
222 # page is nil when previewing a new page
222 # page is nil when previewing a new page
223 return render_403 unless page.nil? || editable?(page)
223 return render_403 unless page.nil? || editable?(page)
224 if page
224 if page
225 @attachements = page.attachments
225 @attachements = page.attachments
226 @previewed = page.content
226 @previewed = page.content
227 end
227 end
228 @text = params[:content][:text]
228 @text = params[:content][:text]
229 render :partial => 'common/preview'
229 render :partial => 'common/preview'
230 end
230 end
231
231
232 def add_attachment
232 def add_attachment
233 return render_403 unless editable?
233 return render_403 unless editable?
234 attachments = Attachment.attach_files(@page, params[:attachments])
234 attachments = Attachment.attach_files(@page, params[:attachments])
235 render_attachment_warning_if_needed(@page)
235 render_attachment_warning_if_needed(@page)
236 redirect_to :action => 'show', :id => @page.title, :project_id => @project
236 redirect_to :action => 'show', :id => @page.title, :project_id => @project
237 end
237 end
238
238
239 private
239 private
240
240
241 def find_wiki
241 def find_wiki
242 @project = Project.find(params[:project_id])
242 @project = Project.find(params[:project_id])
243 @wiki = @project.wiki
243 @wiki = @project.wiki
244 render_404 unless @wiki
244 render_404 unless @wiki
245 rescue ActiveRecord::RecordNotFound
245 rescue ActiveRecord::RecordNotFound
246 render_404
246 render_404
247 end
247 end
248
248
249 # Finds the requested page or a new page if it doesn't exist
249 # Finds the requested page or a new page if it doesn't exist
250 def find_existing_or_new_page
250 def find_existing_or_new_page
251 @page = @wiki.find_or_new_page(params[:id])
251 @page = @wiki.find_or_new_page(params[:id])
252 if @wiki.page_found_with_redirect?
253 redirect_to params.update(:id => @page.title)
254 end
252 end
255 end
253
256
254 # Finds the requested page and returns a 404 error if it doesn't exist
257 # Finds the requested page and returns a 404 error if it doesn't exist
255 def find_existing_page
258 def find_existing_page
256 @page = @wiki.find_page(params[:id])
259 @page = @wiki.find_page(params[:id])
257 render_404 if @page.nil?
260 if @page.nil?
261 render_404
262 return
263 end
264 if @wiki.page_found_with_redirect?
265 redirect_to params.update(:id => @page.title)
266 end
258 end
267 end
259
268
260 # Returns true if the current user is allowed to edit the page, otherwise false
269 # Returns true if the current user is allowed to edit the page, otherwise false
261 def editable?(page = @page)
270 def editable?(page = @page)
262 page.editable_by?(User.current)
271 page.editable_by?(User.current)
263 end
272 end
264
273
265 # Returns the default content of a new wiki page
274 # Returns the default content of a new wiki page
266 def initial_page_content(page)
275 def initial_page_content(page)
267 helper = Redmine::WikiFormatting.helper_for(Setting.text_formatting)
276 helper = Redmine::WikiFormatting.helper_for(Setting.text_formatting)
268 extend helper unless self.instance_of?(helper)
277 extend helper unless self.instance_of?(helper)
269 helper.instance_method(:initial_page_content).bind(self).call(page)
278 helper.instance_method(:initial_page_content).bind(self).call(page)
270 end
279 end
271
280
272 def load_pages_for_index
281 def load_pages_for_index
273 @pages = @wiki.pages.with_updated_on.all(:order => 'title', :include => {:wiki => :project})
282 @pages = @wiki.pages.with_updated_on.all(:order => 'title', :include => {:wiki => :project})
274 end
283 end
275 end
284 end
@@ -1,85 +1,94
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2009 Jean-Philippe Lang
2 # Copyright (C) 2006-2009 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 class Wiki < ActiveRecord::Base
18 class Wiki < ActiveRecord::Base
19 belongs_to :project
19 belongs_to :project
20 has_many :pages, :class_name => 'WikiPage', :dependent => :destroy, :order => 'title'
20 has_many :pages, :class_name => 'WikiPage', :dependent => :destroy, :order => 'title'
21 has_many :redirects, :class_name => 'WikiRedirect', :dependent => :delete_all
21 has_many :redirects, :class_name => 'WikiRedirect', :dependent => :delete_all
22
22
23 acts_as_watchable
23 acts_as_watchable
24
24
25 validates_presence_of :start_page
25 validates_presence_of :start_page
26 validates_format_of :start_page, :with => /^[^,\.\/\?\;\|\:]*$/
26 validates_format_of :start_page, :with => /^[^,\.\/\?\;\|\:]*$/
27
27
28 def visible?(user=User.current)
28 def visible?(user=User.current)
29 !user.nil? && user.allowed_to?(:view_wiki_pages, project)
29 !user.nil? && user.allowed_to?(:view_wiki_pages, project)
30 end
30 end
31
31
32 # Returns the wiki page that acts as the sidebar content
32 # Returns the wiki page that acts as the sidebar content
33 # or nil if no such page exists
33 # or nil if no such page exists
34 def sidebar
34 def sidebar
35 @sidebar ||= find_page('Sidebar', :with_redirect => false)
35 @sidebar ||= find_page('Sidebar', :with_redirect => false)
36 end
36 end
37
37
38 # find the page with the given title
38 # find the page with the given title
39 # if page doesn't exist, return a new page
39 # if page doesn't exist, return a new page
40 def find_or_new_page(title)
40 def find_or_new_page(title)
41 title = start_page if title.blank?
41 title = start_page if title.blank?
42 find_page(title) || WikiPage.new(:wiki => self, :title => Wiki.titleize(title))
42 find_page(title) || WikiPage.new(:wiki => self, :title => Wiki.titleize(title))
43 end
43 end
44
44
45 # find the page with the given title
45 # find the page with the given title
46 def find_page(title, options = {})
46 def find_page(title, options = {})
47 @page_found_with_redirect = false
47 title = start_page if title.blank?
48 title = start_page if title.blank?
48 title = Wiki.titleize(title)
49 title = Wiki.titleize(title)
49 page = pages.first(:conditions => ["LOWER(title) = LOWER(?)", title])
50 page = pages.first(:conditions => ["LOWER(title) = LOWER(?)", title])
50 if !page && !(options[:with_redirect] == false)
51 if !page && !(options[:with_redirect] == false)
51 # search for a redirect
52 # search for a redirect
52 redirect = redirects.first(:conditions => ["LOWER(title) = LOWER(?)", title])
53 redirect = redirects.first(:conditions => ["LOWER(title) = LOWER(?)", title])
53 page = find_page(redirect.redirects_to, :with_redirect => false) if redirect
54 if redirect
55 page = find_page(redirect.redirects_to, :with_redirect => false)
56 @page_found_with_redirect = true
57 end
54 end
58 end
55 page
59 page
56 end
60 end
57
61
62 # Returns true if the last page was found with a redirect
63 def page_found_with_redirect?
64 @page_found_with_redirect
65 end
66
58 # Finds a page by title
67 # Finds a page by title
59 # The given string can be of one of the forms: "title" or "project:title"
68 # The given string can be of one of the forms: "title" or "project:title"
60 # Examples:
69 # Examples:
61 # Wiki.find_page("bar", project => foo)
70 # Wiki.find_page("bar", project => foo)
62 # Wiki.find_page("foo:bar")
71 # Wiki.find_page("foo:bar")
63 def self.find_page(title, options = {})
72 def self.find_page(title, options = {})
64 project = options[:project]
73 project = options[:project]
65 if title.to_s =~ %r{^([^\:]+)\:(.*)$}
74 if title.to_s =~ %r{^([^\:]+)\:(.*)$}
66 project_identifier, title = $1, $2
75 project_identifier, title = $1, $2
67 project = Project.find_by_identifier(project_identifier) || Project.find_by_name(project_identifier)
76 project = Project.find_by_identifier(project_identifier) || Project.find_by_name(project_identifier)
68 end
77 end
69 if project && project.wiki
78 if project && project.wiki
70 page = project.wiki.find_page(title)
79 page = project.wiki.find_page(title)
71 if page && page.content
80 if page && page.content
72 page
81 page
73 end
82 end
74 end
83 end
75 end
84 end
76
85
77 # turn a string into a valid page title
86 # turn a string into a valid page title
78 def self.titleize(title)
87 def self.titleize(title)
79 # replace spaces with _ and remove unwanted caracters
88 # replace spaces with _ and remove unwanted caracters
80 title = title.gsub(/\s+/, '_').delete(',./?;|:') if title
89 title = title.gsub(/\s+/, '_').delete(',./?;|:') if title
81 # upcase the first letter
90 # upcase the first letter
82 title = (title.slice(0..0).upcase + (title.slice(1..-1) || '')) if title
91 title = (title.slice(0..0).upcase + (title.slice(1..-1) || '')) if title
83 title
92 title
84 end
93 end
85 end
94 end
@@ -1,504 +1,511
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2011 Jean-Philippe Lang
2 # Copyright (C) 2006-2011 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 require 'wiki_controller'
19 require 'wiki_controller'
20
20
21 # Re-raise errors caught by the controller.
21 # Re-raise errors caught by the controller.
22 class WikiController; def rescue_action(e) raise e end; end
22 class WikiController; def rescue_action(e) raise e end; end
23
23
24 class WikiControllerTest < ActionController::TestCase
24 class WikiControllerTest < ActionController::TestCase
25 fixtures :projects, :users, :roles, :members, :member_roles, :enabled_modules, :wikis, :wiki_pages, :wiki_contents, :wiki_content_versions, :attachments
25 fixtures :projects, :users, :roles, :members, :member_roles, :enabled_modules, :wikis, :wiki_pages, :wiki_contents, :wiki_content_versions, :attachments
26
26
27 def setup
27 def setup
28 @controller = WikiController.new
28 @controller = WikiController.new
29 @request = ActionController::TestRequest.new
29 @request = ActionController::TestRequest.new
30 @response = ActionController::TestResponse.new
30 @response = ActionController::TestResponse.new
31 User.current = nil
31 User.current = nil
32 end
32 end
33
33
34 def test_show_start_page
34 def test_show_start_page
35 get :show, :project_id => 'ecookbook'
35 get :show, :project_id => 'ecookbook'
36 assert_response :success
36 assert_response :success
37 assert_template 'show'
37 assert_template 'show'
38 assert_tag :tag => 'h1', :content => /CookBook documentation/
38 assert_tag :tag => 'h1', :content => /CookBook documentation/
39
39
40 # child_pages macro
40 # child_pages macro
41 assert_tag :ul, :attributes => { :class => 'pages-hierarchy' },
41 assert_tag :ul, :attributes => { :class => 'pages-hierarchy' },
42 :child => { :tag => 'li',
42 :child => { :tag => 'li',
43 :child => { :tag => 'a', :attributes => { :href => '/projects/ecookbook/wiki/Page_with_an_inline_image' },
43 :child => { :tag => 'a', :attributes => { :href => '/projects/ecookbook/wiki/Page_with_an_inline_image' },
44 :content => 'Page with an inline image' } }
44 :content => 'Page with an inline image' } }
45 end
45 end
46
46
47 def test_show_page_with_name
47 def test_show_page_with_name
48 get :show, :project_id => 1, :id => 'Another_page'
48 get :show, :project_id => 1, :id => 'Another_page'
49 assert_response :success
49 assert_response :success
50 assert_template 'show'
50 assert_template 'show'
51 assert_tag :tag => 'h1', :content => /Another page/
51 assert_tag :tag => 'h1', :content => /Another page/
52 # Included page with an inline image
52 # Included page with an inline image
53 assert_tag :tag => 'p', :content => /This is an inline image/
53 assert_tag :tag => 'p', :content => /This is an inline image/
54 assert_tag :tag => 'img', :attributes => { :src => '/attachments/download/3',
54 assert_tag :tag => 'img', :attributes => { :src => '/attachments/download/3',
55 :alt => 'This is a logo' }
55 :alt => 'This is a logo' }
56 end
56 end
57
57
58 def test_show_redirected_page
59 WikiRedirect.create!(:wiki_id => 1, :title => 'Old_title', :redirects_to => 'Another_page')
60
61 get :show, :project_id => 'ecookbook', :id => 'Old_title'
62 assert_redirected_to '/projects/ecookbook/wiki/Another_page'
63 end
64
58 def test_show_with_sidebar
65 def test_show_with_sidebar
59 page = Project.find(1).wiki.pages.new(:title => 'Sidebar')
66 page = Project.find(1).wiki.pages.new(:title => 'Sidebar')
60 page.content = WikiContent.new(:text => 'Side bar content for test_show_with_sidebar')
67 page.content = WikiContent.new(:text => 'Side bar content for test_show_with_sidebar')
61 page.save!
68 page.save!
62
69
63 get :show, :project_id => 1, :id => 'Another_page'
70 get :show, :project_id => 1, :id => 'Another_page'
64 assert_response :success
71 assert_response :success
65 assert_tag :tag => 'div', :attributes => {:id => 'sidebar'},
72 assert_tag :tag => 'div', :attributes => {:id => 'sidebar'},
66 :content => /Side bar content for test_show_with_sidebar/
73 :content => /Side bar content for test_show_with_sidebar/
67 end
74 end
68
75
69 def test_show_unexistent_page_without_edit_right
76 def test_show_unexistent_page_without_edit_right
70 get :show, :project_id => 1, :id => 'Unexistent page'
77 get :show, :project_id => 1, :id => 'Unexistent page'
71 assert_response 404
78 assert_response 404
72 end
79 end
73
80
74 def test_show_unexistent_page_with_edit_right
81 def test_show_unexistent_page_with_edit_right
75 @request.session[:user_id] = 2
82 @request.session[:user_id] = 2
76 get :show, :project_id => 1, :id => 'Unexistent page'
83 get :show, :project_id => 1, :id => 'Unexistent page'
77 assert_response :success
84 assert_response :success
78 assert_template 'edit'
85 assert_template 'edit'
79 end
86 end
80
87
81 def test_create_page
88 def test_create_page
82 @request.session[:user_id] = 2
89 @request.session[:user_id] = 2
83 put :update, :project_id => 1,
90 put :update, :project_id => 1,
84 :id => 'New page',
91 :id => 'New page',
85 :content => {:comments => 'Created the page',
92 :content => {:comments => 'Created the page',
86 :text => "h1. New page\n\nThis is a new page",
93 :text => "h1. New page\n\nThis is a new page",
87 :version => 0}
94 :version => 0}
88 assert_redirected_to :action => 'show', :project_id => 'ecookbook', :id => 'New_page'
95 assert_redirected_to :action => 'show', :project_id => 'ecookbook', :id => 'New_page'
89 page = Project.find(1).wiki.find_page('New page')
96 page = Project.find(1).wiki.find_page('New page')
90 assert !page.new_record?
97 assert !page.new_record?
91 assert_not_nil page.content
98 assert_not_nil page.content
92 assert_equal 'Created the page', page.content.comments
99 assert_equal 'Created the page', page.content.comments
93 end
100 end
94
101
95 def test_create_page_with_attachments
102 def test_create_page_with_attachments
96 @request.session[:user_id] = 2
103 @request.session[:user_id] = 2
97 assert_difference 'WikiPage.count' do
104 assert_difference 'WikiPage.count' do
98 assert_difference 'Attachment.count' do
105 assert_difference 'Attachment.count' do
99 put :update, :project_id => 1,
106 put :update, :project_id => 1,
100 :id => 'New page',
107 :id => 'New page',
101 :content => {:comments => 'Created the page',
108 :content => {:comments => 'Created the page',
102 :text => "h1. New page\n\nThis is a new page",
109 :text => "h1. New page\n\nThis is a new page",
103 :version => 0},
110 :version => 0},
104 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
111 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
105 end
112 end
106 end
113 end
107 page = Project.find(1).wiki.find_page('New page')
114 page = Project.find(1).wiki.find_page('New page')
108 assert_equal 1, page.attachments.count
115 assert_equal 1, page.attachments.count
109 assert_equal 'testfile.txt', page.attachments.first.filename
116 assert_equal 'testfile.txt', page.attachments.first.filename
110 end
117 end
111
118
112 def test_update_page
119 def test_update_page
113 @request.session[:user_id] = 2
120 @request.session[:user_id] = 2
114 assert_no_difference 'WikiPage.count' do
121 assert_no_difference 'WikiPage.count' do
115 assert_no_difference 'WikiContent.count' do
122 assert_no_difference 'WikiContent.count' do
116 assert_difference 'WikiContent::Version.count' do
123 assert_difference 'WikiContent::Version.count' do
117 put :update, :project_id => 1,
124 put :update, :project_id => 1,
118 :id => 'Another_page',
125 :id => 'Another_page',
119 :content => {
126 :content => {
120 :comments => "my comments",
127 :comments => "my comments",
121 :text => "edited",
128 :text => "edited",
122 :version => 1
129 :version => 1
123 }
130 }
124 end
131 end
125 end
132 end
126 end
133 end
127 assert_redirected_to '/projects/ecookbook/wiki/Another_page'
134 assert_redirected_to '/projects/ecookbook/wiki/Another_page'
128
135
129 page = Wiki.find(1).pages.find_by_title('Another_page')
136 page = Wiki.find(1).pages.find_by_title('Another_page')
130 assert_equal "edited", page.content.text
137 assert_equal "edited", page.content.text
131 assert_equal 2, page.content.version
138 assert_equal 2, page.content.version
132 assert_equal "my comments", page.content.comments
139 assert_equal "my comments", page.content.comments
133 end
140 end
134
141
135 def test_update_page_with_failure
142 def test_update_page_with_failure
136 @request.session[:user_id] = 2
143 @request.session[:user_id] = 2
137 assert_no_difference 'WikiPage.count' do
144 assert_no_difference 'WikiPage.count' do
138 assert_no_difference 'WikiContent.count' do
145 assert_no_difference 'WikiContent.count' do
139 assert_no_difference 'WikiContent::Version.count' do
146 assert_no_difference 'WikiContent::Version.count' do
140 put :update, :project_id => 1,
147 put :update, :project_id => 1,
141 :id => 'Another_page',
148 :id => 'Another_page',
142 :content => {
149 :content => {
143 :comments => 'a' * 300, # failure here, comment is too long
150 :comments => 'a' * 300, # failure here, comment is too long
144 :text => 'edited',
151 :text => 'edited',
145 :version => 1
152 :version => 1
146 }
153 }
147 end
154 end
148 end
155 end
149 end
156 end
150 assert_response :success
157 assert_response :success
151 assert_template 'edit'
158 assert_template 'edit'
152
159
153 assert_error_tag :descendant => {:content => /Comment is too long/}
160 assert_error_tag :descendant => {:content => /Comment is too long/}
154 assert_tag :tag => 'textarea', :attributes => {:id => 'content_text'}, :content => 'edited'
161 assert_tag :tag => 'textarea', :attributes => {:id => 'content_text'}, :content => 'edited'
155 assert_tag :tag => 'input', :attributes => {:id => 'content_version', :value => '1'}
162 assert_tag :tag => 'input', :attributes => {:id => 'content_version', :value => '1'}
156 end
163 end
157
164
158 def test_update_stale_page_should_not_raise_an_error
165 def test_update_stale_page_should_not_raise_an_error
159 @request.session[:user_id] = 2
166 @request.session[:user_id] = 2
160 c = Wiki.find(1).find_page('Another_page').content
167 c = Wiki.find(1).find_page('Another_page').content
161 c.text = 'Previous text'
168 c.text = 'Previous text'
162 c.save!
169 c.save!
163 assert_equal 2, c.version
170 assert_equal 2, c.version
164
171
165 assert_no_difference 'WikiPage.count' do
172 assert_no_difference 'WikiPage.count' do
166 assert_no_difference 'WikiContent.count' do
173 assert_no_difference 'WikiContent.count' do
167 assert_no_difference 'WikiContent::Version.count' do
174 assert_no_difference 'WikiContent::Version.count' do
168 put :update, :project_id => 1,
175 put :update, :project_id => 1,
169 :id => 'Another_page',
176 :id => 'Another_page',
170 :content => {
177 :content => {
171 :comments => 'My comments',
178 :comments => 'My comments',
172 :text => 'Text should not be lost',
179 :text => 'Text should not be lost',
173 :version => 1
180 :version => 1
174 }
181 }
175 end
182 end
176 end
183 end
177 end
184 end
178 assert_response :success
185 assert_response :success
179 assert_template 'edit'
186 assert_template 'edit'
180 assert_tag :div,
187 assert_tag :div,
181 :attributes => { :class => /error/ },
188 :attributes => { :class => /error/ },
182 :content => /Data has been updated by another user/
189 :content => /Data has been updated by another user/
183 assert_tag 'textarea',
190 assert_tag 'textarea',
184 :attributes => { :name => 'content[text]' },
191 :attributes => { :name => 'content[text]' },
185 :content => /Text should not be lost/
192 :content => /Text should not be lost/
186 assert_tag 'input',
193 assert_tag 'input',
187 :attributes => { :name => 'content[comments]', :value => 'My comments' }
194 :attributes => { :name => 'content[comments]', :value => 'My comments' }
188
195
189 c.reload
196 c.reload
190 assert_equal 'Previous text', c.text
197 assert_equal 'Previous text', c.text
191 assert_equal 2, c.version
198 assert_equal 2, c.version
192 end
199 end
193
200
194 def test_preview
201 def test_preview
195 @request.session[:user_id] = 2
202 @request.session[:user_id] = 2
196 xhr :post, :preview, :project_id => 1, :id => 'CookBook_documentation',
203 xhr :post, :preview, :project_id => 1, :id => 'CookBook_documentation',
197 :content => { :comments => '',
204 :content => { :comments => '',
198 :text => 'this is a *previewed text*',
205 :text => 'this is a *previewed text*',
199 :version => 3 }
206 :version => 3 }
200 assert_response :success
207 assert_response :success
201 assert_template 'common/_preview'
208 assert_template 'common/_preview'
202 assert_tag :tag => 'strong', :content => /previewed text/
209 assert_tag :tag => 'strong', :content => /previewed text/
203 end
210 end
204
211
205 def test_preview_new_page
212 def test_preview_new_page
206 @request.session[:user_id] = 2
213 @request.session[:user_id] = 2
207 xhr :post, :preview, :project_id => 1, :id => 'New page',
214 xhr :post, :preview, :project_id => 1, :id => 'New page',
208 :content => { :text => 'h1. New page',
215 :content => { :text => 'h1. New page',
209 :comments => '',
216 :comments => '',
210 :version => 0 }
217 :version => 0 }
211 assert_response :success
218 assert_response :success
212 assert_template 'common/_preview'
219 assert_template 'common/_preview'
213 assert_tag :tag => 'h1', :content => /New page/
220 assert_tag :tag => 'h1', :content => /New page/
214 end
221 end
215
222
216 def test_history
223 def test_history
217 get :history, :project_id => 1, :id => 'CookBook_documentation'
224 get :history, :project_id => 1, :id => 'CookBook_documentation'
218 assert_response :success
225 assert_response :success
219 assert_template 'history'
226 assert_template 'history'
220 assert_not_nil assigns(:versions)
227 assert_not_nil assigns(:versions)
221 assert_equal 3, assigns(:versions).size
228 assert_equal 3, assigns(:versions).size
222 assert_select "input[type=submit][name=commit]"
229 assert_select "input[type=submit][name=commit]"
223 end
230 end
224
231
225 def test_history_with_one_version
232 def test_history_with_one_version
226 get :history, :project_id => 1, :id => 'Another_page'
233 get :history, :project_id => 1, :id => 'Another_page'
227 assert_response :success
234 assert_response :success
228 assert_template 'history'
235 assert_template 'history'
229 assert_not_nil assigns(:versions)
236 assert_not_nil assigns(:versions)
230 assert_equal 1, assigns(:versions).size
237 assert_equal 1, assigns(:versions).size
231 assert_select "input[type=submit][name=commit]", false
238 assert_select "input[type=submit][name=commit]", false
232 end
239 end
233
240
234 def test_diff
241 def test_diff
235 get :diff, :project_id => 1, :id => 'CookBook_documentation', :version => 2, :version_from => 1
242 get :diff, :project_id => 1, :id => 'CookBook_documentation', :version => 2, :version_from => 1
236 assert_response :success
243 assert_response :success
237 assert_template 'diff'
244 assert_template 'diff'
238 assert_tag :tag => 'span', :attributes => { :class => 'diff_in'},
245 assert_tag :tag => 'span', :attributes => { :class => 'diff_in'},
239 :content => /updated/
246 :content => /updated/
240 end
247 end
241
248
242 def test_annotate
249 def test_annotate
243 get :annotate, :project_id => 1, :id => 'CookBook_documentation', :version => 2
250 get :annotate, :project_id => 1, :id => 'CookBook_documentation', :version => 2
244 assert_response :success
251 assert_response :success
245 assert_template 'annotate'
252 assert_template 'annotate'
246 # Line 1
253 # Line 1
247 assert_tag :tag => 'tr', :child => { :tag => 'th', :attributes => {:class => 'line-num'}, :content => '1' },
254 assert_tag :tag => 'tr', :child => { :tag => 'th', :attributes => {:class => 'line-num'}, :content => '1' },
248 :child => { :tag => 'td', :attributes => {:class => 'author'}, :content => /John Smith/ },
255 :child => { :tag => 'td', :attributes => {:class => 'author'}, :content => /John Smith/ },
249 :child => { :tag => 'td', :content => /h1\. CookBook documentation/ }
256 :child => { :tag => 'td', :content => /h1\. CookBook documentation/ }
250 # Line 2
257 # Line 2
251 assert_tag :tag => 'tr', :child => { :tag => 'th', :attributes => {:class => 'line-num'}, :content => '2' },
258 assert_tag :tag => 'tr', :child => { :tag => 'th', :attributes => {:class => 'line-num'}, :content => '2' },
252 :child => { :tag => 'td', :attributes => {:class => 'author'}, :content => /redMine Admin/ },
259 :child => { :tag => 'td', :attributes => {:class => 'author'}, :content => /redMine Admin/ },
253 :child => { :tag => 'td', :content => /Some updated \[\[documentation\]\] here/ }
260 :child => { :tag => 'td', :content => /Some updated \[\[documentation\]\] here/ }
254 end
261 end
255
262
256 def test_get_rename
263 def test_get_rename
257 @request.session[:user_id] = 2
264 @request.session[:user_id] = 2
258 get :rename, :project_id => 1, :id => 'Another_page'
265 get :rename, :project_id => 1, :id => 'Another_page'
259 assert_response :success
266 assert_response :success
260 assert_template 'rename'
267 assert_template 'rename'
261 assert_tag 'option',
268 assert_tag 'option',
262 :attributes => {:value => ''},
269 :attributes => {:value => ''},
263 :content => '',
270 :content => '',
264 :parent => {:tag => 'select', :attributes => {:name => 'wiki_page[parent_id]'}}
271 :parent => {:tag => 'select', :attributes => {:name => 'wiki_page[parent_id]'}}
265 assert_no_tag 'option',
272 assert_no_tag 'option',
266 :attributes => {:selected => 'selected'},
273 :attributes => {:selected => 'selected'},
267 :parent => {:tag => 'select', :attributes => {:name => 'wiki_page[parent_id]'}}
274 :parent => {:tag => 'select', :attributes => {:name => 'wiki_page[parent_id]'}}
268 end
275 end
269
276
270 def test_get_rename_child_page
277 def test_get_rename_child_page
271 @request.session[:user_id] = 2
278 @request.session[:user_id] = 2
272 get :rename, :project_id => 1, :id => 'Child_1'
279 get :rename, :project_id => 1, :id => 'Child_1'
273 assert_response :success
280 assert_response :success
274 assert_template 'rename'
281 assert_template 'rename'
275 assert_tag 'option',
282 assert_tag 'option',
276 :attributes => {:value => ''},
283 :attributes => {:value => ''},
277 :content => '',
284 :content => '',
278 :parent => {:tag => 'select', :attributes => {:name => 'wiki_page[parent_id]'}}
285 :parent => {:tag => 'select', :attributes => {:name => 'wiki_page[parent_id]'}}
279 assert_tag 'option',
286 assert_tag 'option',
280 :attributes => {:value => '2', :selected => 'selected'},
287 :attributes => {:value => '2', :selected => 'selected'},
281 :content => /Another page/,
288 :content => /Another page/,
282 :parent => {
289 :parent => {
283 :tag => 'select',
290 :tag => 'select',
284 :attributes => {:name => 'wiki_page[parent_id]'}
291 :attributes => {:name => 'wiki_page[parent_id]'}
285 }
292 }
286 end
293 end
287
294
288 def test_rename_with_redirect
295 def test_rename_with_redirect
289 @request.session[:user_id] = 2
296 @request.session[:user_id] = 2
290 post :rename, :project_id => 1, :id => 'Another_page',
297 post :rename, :project_id => 1, :id => 'Another_page',
291 :wiki_page => { :title => 'Another renamed page',
298 :wiki_page => { :title => 'Another renamed page',
292 :redirect_existing_links => 1 }
299 :redirect_existing_links => 1 }
293 assert_redirected_to :action => 'show', :project_id => 'ecookbook', :id => 'Another_renamed_page'
300 assert_redirected_to :action => 'show', :project_id => 'ecookbook', :id => 'Another_renamed_page'
294 wiki = Project.find(1).wiki
301 wiki = Project.find(1).wiki
295 # Check redirects
302 # Check redirects
296 assert_not_nil wiki.find_page('Another page')
303 assert_not_nil wiki.find_page('Another page')
297 assert_nil wiki.find_page('Another page', :with_redirect => false)
304 assert_nil wiki.find_page('Another page', :with_redirect => false)
298 end
305 end
299
306
300 def test_rename_without_redirect
307 def test_rename_without_redirect
301 @request.session[:user_id] = 2
308 @request.session[:user_id] = 2
302 post :rename, :project_id => 1, :id => 'Another_page',
309 post :rename, :project_id => 1, :id => 'Another_page',
303 :wiki_page => { :title => 'Another renamed page',
310 :wiki_page => { :title => 'Another renamed page',
304 :redirect_existing_links => "0" }
311 :redirect_existing_links => "0" }
305 assert_redirected_to :action => 'show', :project_id => 'ecookbook', :id => 'Another_renamed_page'
312 assert_redirected_to :action => 'show', :project_id => 'ecookbook', :id => 'Another_renamed_page'
306 wiki = Project.find(1).wiki
313 wiki = Project.find(1).wiki
307 # Check that there's no redirects
314 # Check that there's no redirects
308 assert_nil wiki.find_page('Another page')
315 assert_nil wiki.find_page('Another page')
309 end
316 end
310
317
311 def test_rename_with_parent_assignment
318 def test_rename_with_parent_assignment
312 @request.session[:user_id] = 2
319 @request.session[:user_id] = 2
313 post :rename, :project_id => 1, :id => 'Another_page',
320 post :rename, :project_id => 1, :id => 'Another_page',
314 :wiki_page => { :title => 'Another page', :redirect_existing_links => "0", :parent_id => '4' }
321 :wiki_page => { :title => 'Another page', :redirect_existing_links => "0", :parent_id => '4' }
315 assert_redirected_to :action => 'show', :project_id => 'ecookbook', :id => 'Another_page'
322 assert_redirected_to :action => 'show', :project_id => 'ecookbook', :id => 'Another_page'
316 assert_equal WikiPage.find(4), WikiPage.find_by_title('Another_page').parent
323 assert_equal WikiPage.find(4), WikiPage.find_by_title('Another_page').parent
317 end
324 end
318
325
319 def test_rename_with_parent_unassignment
326 def test_rename_with_parent_unassignment
320 @request.session[:user_id] = 2
327 @request.session[:user_id] = 2
321 post :rename, :project_id => 1, :id => 'Child_1',
328 post :rename, :project_id => 1, :id => 'Child_1',
322 :wiki_page => { :title => 'Child 1', :redirect_existing_links => "0", :parent_id => '' }
329 :wiki_page => { :title => 'Child 1', :redirect_existing_links => "0", :parent_id => '' }
323 assert_redirected_to :action => 'show', :project_id => 'ecookbook', :id => 'Child_1'
330 assert_redirected_to :action => 'show', :project_id => 'ecookbook', :id => 'Child_1'
324 assert_nil WikiPage.find_by_title('Child_1').parent
331 assert_nil WikiPage.find_by_title('Child_1').parent
325 end
332 end
326
333
327 def test_destroy_child
334 def test_destroy_child
328 @request.session[:user_id] = 2
335 @request.session[:user_id] = 2
329 delete :destroy, :project_id => 1, :id => 'Child_1'
336 delete :destroy, :project_id => 1, :id => 'Child_1'
330 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
337 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
331 end
338 end
332
339
333 def test_destroy_parent
340 def test_destroy_parent
334 @request.session[:user_id] = 2
341 @request.session[:user_id] = 2
335 assert_no_difference('WikiPage.count') do
342 assert_no_difference('WikiPage.count') do
336 delete :destroy, :project_id => 1, :id => 'Another_page'
343 delete :destroy, :project_id => 1, :id => 'Another_page'
337 end
344 end
338 assert_response :success
345 assert_response :success
339 assert_template 'destroy'
346 assert_template 'destroy'
340 end
347 end
341
348
342 def test_destroy_parent_with_nullify
349 def test_destroy_parent_with_nullify
343 @request.session[:user_id] = 2
350 @request.session[:user_id] = 2
344 assert_difference('WikiPage.count', -1) do
351 assert_difference('WikiPage.count', -1) do
345 delete :destroy, :project_id => 1, :id => 'Another_page', :todo => 'nullify'
352 delete :destroy, :project_id => 1, :id => 'Another_page', :todo => 'nullify'
346 end
353 end
347 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
354 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
348 assert_nil WikiPage.find_by_id(2)
355 assert_nil WikiPage.find_by_id(2)
349 end
356 end
350
357
351 def test_destroy_parent_with_cascade
358 def test_destroy_parent_with_cascade
352 @request.session[:user_id] = 2
359 @request.session[:user_id] = 2
353 assert_difference('WikiPage.count', -3) do
360 assert_difference('WikiPage.count', -3) do
354 delete :destroy, :project_id => 1, :id => 'Another_page', :todo => 'destroy'
361 delete :destroy, :project_id => 1, :id => 'Another_page', :todo => 'destroy'
355 end
362 end
356 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
363 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
357 assert_nil WikiPage.find_by_id(2)
364 assert_nil WikiPage.find_by_id(2)
358 assert_nil WikiPage.find_by_id(5)
365 assert_nil WikiPage.find_by_id(5)
359 end
366 end
360
367
361 def test_destroy_parent_with_reassign
368 def test_destroy_parent_with_reassign
362 @request.session[:user_id] = 2
369 @request.session[:user_id] = 2
363 assert_difference('WikiPage.count', -1) do
370 assert_difference('WikiPage.count', -1) do
364 delete :destroy, :project_id => 1, :id => 'Another_page', :todo => 'reassign', :reassign_to_id => 1
371 delete :destroy, :project_id => 1, :id => 'Another_page', :todo => 'reassign', :reassign_to_id => 1
365 end
372 end
366 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
373 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
367 assert_nil WikiPage.find_by_id(2)
374 assert_nil WikiPage.find_by_id(2)
368 assert_equal WikiPage.find(1), WikiPage.find_by_id(5).parent
375 assert_equal WikiPage.find(1), WikiPage.find_by_id(5).parent
369 end
376 end
370
377
371 def test_index
378 def test_index
372 get :index, :project_id => 'ecookbook'
379 get :index, :project_id => 'ecookbook'
373 assert_response :success
380 assert_response :success
374 assert_template 'index'
381 assert_template 'index'
375 pages = assigns(:pages)
382 pages = assigns(:pages)
376 assert_not_nil pages
383 assert_not_nil pages
377 assert_equal Project.find(1).wiki.pages.size, pages.size
384 assert_equal Project.find(1).wiki.pages.size, pages.size
378 assert_equal pages.first.content.updated_on, pages.first.updated_on
385 assert_equal pages.first.content.updated_on, pages.first.updated_on
379
386
380 assert_tag :ul, :attributes => { :class => 'pages-hierarchy' },
387 assert_tag :ul, :attributes => { :class => 'pages-hierarchy' },
381 :child => { :tag => 'li', :child => { :tag => 'a', :attributes => { :href => '/projects/ecookbook/wiki/CookBook_documentation' },
388 :child => { :tag => 'li', :child => { :tag => 'a', :attributes => { :href => '/projects/ecookbook/wiki/CookBook_documentation' },
382 :content => 'CookBook documentation' },
389 :content => 'CookBook documentation' },
383 :child => { :tag => 'ul',
390 :child => { :tag => 'ul',
384 :child => { :tag => 'li',
391 :child => { :tag => 'li',
385 :child => { :tag => 'a', :attributes => { :href => '/projects/ecookbook/wiki/Page_with_an_inline_image' },
392 :child => { :tag => 'a', :attributes => { :href => '/projects/ecookbook/wiki/Page_with_an_inline_image' },
386 :content => 'Page with an inline image' } } } },
393 :content => 'Page with an inline image' } } } },
387 :child => { :tag => 'li', :child => { :tag => 'a', :attributes => { :href => '/projects/ecookbook/wiki/Another_page' },
394 :child => { :tag => 'li', :child => { :tag => 'a', :attributes => { :href => '/projects/ecookbook/wiki/Another_page' },
388 :content => 'Another page' } }
395 :content => 'Another page' } }
389 end
396 end
390
397
391 def test_index_should_include_atom_link
398 def test_index_should_include_atom_link
392 get :index, :project_id => 'ecookbook'
399 get :index, :project_id => 'ecookbook'
393 assert_tag 'a', :attributes => { :href => '/projects/ecookbook/activity.atom?show_wiki_edits=1'}
400 assert_tag 'a', :attributes => { :href => '/projects/ecookbook/activity.atom?show_wiki_edits=1'}
394 end
401 end
395
402
396 context "GET :export" do
403 context "GET :export" do
397 context "with an authorized user to export the wiki" do
404 context "with an authorized user to export the wiki" do
398 setup do
405 setup do
399 @request.session[:user_id] = 2
406 @request.session[:user_id] = 2
400 get :export, :project_id => 'ecookbook'
407 get :export, :project_id => 'ecookbook'
401 end
408 end
402
409
403 should_respond_with :success
410 should_respond_with :success
404 should_assign_to :pages
411 should_assign_to :pages
405 should_respond_with_content_type "text/html"
412 should_respond_with_content_type "text/html"
406 should "export all of the wiki pages to a single html file" do
413 should "export all of the wiki pages to a single html file" do
407 assert_select "a[name=?]", "CookBook_documentation"
414 assert_select "a[name=?]", "CookBook_documentation"
408 assert_select "a[name=?]", "Another_page"
415 assert_select "a[name=?]", "Another_page"
409 assert_select "a[name=?]", "Page_with_an_inline_image"
416 assert_select "a[name=?]", "Page_with_an_inline_image"
410 end
417 end
411
418
412 end
419 end
413
420
414 context "with an unauthorized user" do
421 context "with an unauthorized user" do
415 setup do
422 setup do
416 get :export, :project_id => 'ecookbook'
423 get :export, :project_id => 'ecookbook'
417
424
418 should_respond_with :redirect
425 should_respond_with :redirect
419 should_redirect_to('wiki index') { {:action => 'show', :project_id => @project, :id => nil} }
426 should_redirect_to('wiki index') { {:action => 'show', :project_id => @project, :id => nil} }
420 end
427 end
421 end
428 end
422 end
429 end
423
430
424 context "GET :date_index" do
431 context "GET :date_index" do
425 setup do
432 setup do
426 get :date_index, :project_id => 'ecookbook'
433 get :date_index, :project_id => 'ecookbook'
427 end
434 end
428
435
429 should_respond_with :success
436 should_respond_with :success
430 should_assign_to :pages
437 should_assign_to :pages
431 should_assign_to :pages_by_date
438 should_assign_to :pages_by_date
432 should_render_template 'wiki/date_index'
439 should_render_template 'wiki/date_index'
433
440
434 should "include atom link" do
441 should "include atom link" do
435 assert_tag 'a', :attributes => { :href => '/projects/ecookbook/activity.atom?show_wiki_edits=1'}
442 assert_tag 'a', :attributes => { :href => '/projects/ecookbook/activity.atom?show_wiki_edits=1'}
436 end
443 end
437 end
444 end
438
445
439 def test_not_found
446 def test_not_found
440 get :show, :project_id => 999
447 get :show, :project_id => 999
441 assert_response 404
448 assert_response 404
442 end
449 end
443
450
444 def test_protect_page
451 def test_protect_page
445 page = WikiPage.find_by_wiki_id_and_title(1, 'Another_page')
452 page = WikiPage.find_by_wiki_id_and_title(1, 'Another_page')
446 assert !page.protected?
453 assert !page.protected?
447 @request.session[:user_id] = 2
454 @request.session[:user_id] = 2
448 post :protect, :project_id => 1, :id => page.title, :protected => '1'
455 post :protect, :project_id => 1, :id => page.title, :protected => '1'
449 assert_redirected_to :action => 'show', :project_id => 'ecookbook', :id => 'Another_page'
456 assert_redirected_to :action => 'show', :project_id => 'ecookbook', :id => 'Another_page'
450 assert page.reload.protected?
457 assert page.reload.protected?
451 end
458 end
452
459
453 def test_unprotect_page
460 def test_unprotect_page
454 page = WikiPage.find_by_wiki_id_and_title(1, 'CookBook_documentation')
461 page = WikiPage.find_by_wiki_id_and_title(1, 'CookBook_documentation')
455 assert page.protected?
462 assert page.protected?
456 @request.session[:user_id] = 2
463 @request.session[:user_id] = 2
457 post :protect, :project_id => 1, :id => page.title, :protected => '0'
464 post :protect, :project_id => 1, :id => page.title, :protected => '0'
458 assert_redirected_to :action => 'show', :project_id => 'ecookbook', :id => 'CookBook_documentation'
465 assert_redirected_to :action => 'show', :project_id => 'ecookbook', :id => 'CookBook_documentation'
459 assert !page.reload.protected?
466 assert !page.reload.protected?
460 end
467 end
461
468
462 def test_show_page_with_edit_link
469 def test_show_page_with_edit_link
463 @request.session[:user_id] = 2
470 @request.session[:user_id] = 2
464 get :show, :project_id => 1
471 get :show, :project_id => 1
465 assert_response :success
472 assert_response :success
466 assert_template 'show'
473 assert_template 'show'
467 assert_tag :tag => 'a', :attributes => { :href => '/projects/1/wiki/CookBook_documentation/edit' }
474 assert_tag :tag => 'a', :attributes => { :href => '/projects/1/wiki/CookBook_documentation/edit' }
468 end
475 end
469
476
470 def test_show_page_without_edit_link
477 def test_show_page_without_edit_link
471 @request.session[:user_id] = 4
478 @request.session[:user_id] = 4
472 get :show, :project_id => 1
479 get :show, :project_id => 1
473 assert_response :success
480 assert_response :success
474 assert_template 'show'
481 assert_template 'show'
475 assert_no_tag :tag => 'a', :attributes => { :href => '/projects/1/wiki/CookBook_documentation/edit' }
482 assert_no_tag :tag => 'a', :attributes => { :href => '/projects/1/wiki/CookBook_documentation/edit' }
476 end
483 end
477
484
478 def test_edit_unprotected_page
485 def test_edit_unprotected_page
479 # Non members can edit unprotected wiki pages
486 # Non members can edit unprotected wiki pages
480 @request.session[:user_id] = 4
487 @request.session[:user_id] = 4
481 get :edit, :project_id => 1, :id => 'Another_page'
488 get :edit, :project_id => 1, :id => 'Another_page'
482 assert_response :success
489 assert_response :success
483 assert_template 'edit'
490 assert_template 'edit'
484 end
491 end
485
492
486 def test_edit_protected_page_by_nonmember
493 def test_edit_protected_page_by_nonmember
487 # Non members can't edit protected wiki pages
494 # Non members can't edit protected wiki pages
488 @request.session[:user_id] = 4
495 @request.session[:user_id] = 4
489 get :edit, :project_id => 1, :id => 'CookBook_documentation'
496 get :edit, :project_id => 1, :id => 'CookBook_documentation'
490 assert_response 403
497 assert_response 403
491 end
498 end
492
499
493 def test_edit_protected_page_by_member
500 def test_edit_protected_page_by_member
494 @request.session[:user_id] = 2
501 @request.session[:user_id] = 2
495 get :edit, :project_id => 1, :id => 'CookBook_documentation'
502 get :edit, :project_id => 1, :id => 'CookBook_documentation'
496 assert_response :success
503 assert_response :success
497 assert_template 'edit'
504 assert_template 'edit'
498 end
505 end
499
506
500 def test_history_of_non_existing_page_should_return_404
507 def test_history_of_non_existing_page_should_return_404
501 get :history, :project_id => 1, :id => 'Unknown_page'
508 get :history, :project_id => 1, :id => 'Unknown_page'
502 assert_response 404
509 assert_response 404
503 end
510 end
504 end
511 end
@@ -1,80 +1,103
1 # encoding: utf-8
1 # encoding: utf-8
2 #
2 #
3 # redMine - project management software
3 # Redmine - project management software
4 # Copyright (C) 2006-2007 Jean-Philippe Lang
4 # Copyright (C) 2006-2011 Jean-Philippe Lang
5 #
5 #
6 # This program is free software; you can redistribute it and/or
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; either version 2
8 # as published by the Free Software Foundation; either version 2
9 # of the License, or (at your option) any later version.
9 # of the License, or (at your option) any later version.
10 #
10 #
11 # This program is distributed in the hope that it will be useful,
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
14 # GNU General Public License for more details.
15 #
15 #
16 # You should have received a copy of the GNU General Public License
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19
19
20 require File.expand_path('../../test_helper', __FILE__)
20 require File.expand_path('../../test_helper', __FILE__)
21
21
22 class WikiTest < ActiveSupport::TestCase
22 class WikiTest < ActiveSupport::TestCase
23 fixtures :projects, :wikis, :wiki_pages, :wiki_contents, :wiki_content_versions
23 fixtures :projects, :wikis, :wiki_pages, :wiki_contents, :wiki_content_versions
24
24
25 def test_create
25 def test_create
26 wiki = Wiki.new(:project => Project.find(2))
26 wiki = Wiki.new(:project => Project.find(2))
27 assert !wiki.save
27 assert !wiki.save
28 assert_equal 1, wiki.errors.count
28 assert_equal 1, wiki.errors.count
29
29
30 wiki.start_page = "Start page"
30 wiki.start_page = "Start page"
31 assert wiki.save
31 assert wiki.save
32 end
32 end
33
33
34 def test_update
34 def test_update
35 @wiki = Wiki.find(1)
35 @wiki = Wiki.find(1)
36 @wiki.start_page = "Another start page"
36 @wiki.start_page = "Another start page"
37 assert @wiki.save
37 assert @wiki.save
38 @wiki.reload
38 @wiki.reload
39 assert_equal "Another start page", @wiki.start_page
39 assert_equal "Another start page", @wiki.start_page
40 end
40 end
41
41
42 def test_find_page
42 def test_find_page_should_not_be_case_sensitive
43 wiki = Wiki.find(1)
43 wiki = Wiki.find(1)
44 page = WikiPage.find(2)
44 page = WikiPage.find(2)
45
45
46 assert_equal page, wiki.find_page('Another_page')
46 assert_equal page, wiki.find_page('Another_page')
47 assert_equal page, wiki.find_page('Another page')
47 assert_equal page, wiki.find_page('Another page')
48 assert_equal page, wiki.find_page('ANOTHER page')
48 assert_equal page, wiki.find_page('ANOTHER page')
49
49 end
50
51 def test_find_page_with_cyrillic_characters
52 wiki = Wiki.find(1)
50 page = WikiPage.find(10)
53 page = WikiPage.find(10)
51 assert_equal page, wiki.find_page('Этика_менеджмента')
54 assert_equal page, wiki.find_page('Этика_менеджмента')
52
55 end
56
57 def test_find_page_with_backslashes
58 wiki = Wiki.find(1)
53 page = WikiPage.generate!(:wiki => wiki, :title => '2009\\02\\09')
59 page = WikiPage.generate!(:wiki => wiki, :title => '2009\\02\\09')
54 assert_equal page, wiki.find_page('2009\\02\\09')
60 assert_equal page, wiki.find_page('2009\\02\\09')
55 end
61 end
56
62
63 def test_find_page_without_redirect
64 wiki = Wiki.find(1)
65 page = wiki.find_page('Another_page')
66 assert_not_nil page
67 assert_equal 'Another_page', page.title
68 assert_equal false, wiki.page_found_with_redirect?
69 end
70
71 def test_find_page_with_redirect
72 wiki = Wiki.find(1)
73 WikiRedirect.create!(:wiki => wiki, :title => 'Old_title', :redirects_to => 'Another_page')
74 page = wiki.find_page('Old_title')
75 assert_not_nil page
76 assert_equal 'Another_page', page.title
77 assert_equal true, wiki.page_found_with_redirect?
78 end
79
57 def test_titleize
80 def test_titleize
58 assert_equal 'Page_title_with_CAPITALES', Wiki.titleize('page title with CAPITALES')
81 assert_equal 'Page_title_with_CAPITALES', Wiki.titleize('page title with CAPITALES')
59 assert_equal 'テスト', Wiki.titleize('テスト')
82 assert_equal 'テスト', Wiki.titleize('テスト')
60 end
83 end
61
84
62 context "#sidebar" do
85 context "#sidebar" do
63 setup do
86 setup do
64 @wiki = Wiki.find(1)
87 @wiki = Wiki.find(1)
65 end
88 end
66
89
67 should "return nil if undefined" do
90 should "return nil if undefined" do
68 assert_nil @wiki.sidebar
91 assert_nil @wiki.sidebar
69 end
92 end
70
93
71 should "return a WikiPage if defined" do
94 should "return a WikiPage if defined" do
72 page = @wiki.pages.new(:title => 'Sidebar')
95 page = @wiki.pages.new(:title => 'Sidebar')
73 page.content = WikiContent.new(:text => 'Side bar content for test_show_with_sidebar')
96 page.content = WikiContent.new(:text => 'Side bar content for test_show_with_sidebar')
74 page.save!
97 page.save!
75
98
76 assert_kind_of WikiPage, @wiki.sidebar
99 assert_kind_of WikiPage, @wiki.sidebar
77 assert_equal 'Sidebar', @wiki.sidebar.title
100 assert_equal 'Sidebar', @wiki.sidebar.title
78 end
101 end
79 end
102 end
80 end
103 end
General Comments 0
You need to be logged in to leave comments. Login now