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