##// END OF EJS Templates
Merged r6206 from trunk....
Jean-Philippe Lang -
r6087:a8550ba8a633
parent child
Show More
@@ -1,217 +1,221
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 require 'enumerator'
20 20
21 21 class WikiPage < ActiveRecord::Base
22 22 belongs_to :wiki
23 23 has_one :content, :class_name => 'WikiContent', :foreign_key => 'page_id', :dependent => :destroy
24 24 acts_as_attachable :delete_permission => :delete_wiki_pages_attachments
25 25 acts_as_tree :dependent => :nullify, :order => 'title'
26 26
27 27 acts_as_watchable
28 28 acts_as_event :title => Proc.new {|o| "#{l(:label_wiki)}: #{o.title}"},
29 29 :description => :text,
30 30 :datetime => :created_on,
31 31 :url => Proc.new {|o| {:controller => 'wiki', :action => 'show', :project_id => o.wiki.project, :id => o.title}}
32 32
33 33 acts_as_searchable :columns => ['title', 'text'],
34 34 :include => [{:wiki => :project}, :content],
35 35 :permission => :view_wiki_pages,
36 36 :project_key => "#{Wiki.table_name}.project_id"
37 37
38 38 attr_accessor :redirect_existing_links
39 39
40 40 validates_presence_of :title
41 41 validates_format_of :title, :with => /^[^,\.\/\?\;\|\s]*$/
42 42 validates_uniqueness_of :title, :scope => :wiki_id, :case_sensitive => false
43 43 validates_associated :content
44 44
45 45 # eager load information about last updates, without loading text
46 46 named_scope :with_updated_on, {
47 47 :select => "#{WikiPage.table_name}.*, #{WikiContent.table_name}.updated_on",
48 48 :joins => "LEFT JOIN #{WikiContent.table_name} ON #{WikiContent.table_name}.page_id = #{WikiPage.table_name}.id"
49 49 }
50 50
51 51 # Wiki pages that are protected by default
52 52 DEFAULT_PROTECTED_PAGES = %w(sidebar)
53 53
54 54 def after_initialize
55 55 if new_record? && DEFAULT_PROTECTED_PAGES.include?(title.to_s.downcase)
56 56 self.protected = true
57 57 end
58 58 end
59 59
60 60 def visible?(user=User.current)
61 61 !user.nil? && user.allowed_to?(:view_wiki_pages, project)
62 62 end
63 63
64 64 def title=(value)
65 65 value = Wiki.titleize(value)
66 66 @previous_title = read_attribute(:title) if @previous_title.blank?
67 67 write_attribute(:title, value)
68 68 end
69 69
70 70 def before_save
71 71 self.title = Wiki.titleize(title)
72 72 # Manage redirects if the title has changed
73 73 if !@previous_title.blank? && (@previous_title != title) && !new_record?
74 74 # Update redirects that point to the old title
75 75 wiki.redirects.find_all_by_redirects_to(@previous_title).each do |r|
76 76 r.redirects_to = title
77 77 r.title == r.redirects_to ? r.destroy : r.save
78 78 end
79 79 # Remove redirects for the new title
80 80 wiki.redirects.find_all_by_title(title).each(&:destroy)
81 81 # Create a redirect to the new title
82 82 wiki.redirects << WikiRedirect.new(:title => @previous_title, :redirects_to => title) unless redirect_existing_links == "0"
83 83 @previous_title = nil
84 84 end
85 85 end
86 86
87 87 def before_destroy
88 88 # Remove redirects to this page
89 89 wiki.redirects.find_all_by_redirects_to(title).each(&:destroy)
90 90 end
91 91
92 92 def pretty_title
93 93 WikiPage.pretty_title(title)
94 94 end
95 95
96 96 def content_for_version(version=nil)
97 97 result = content.versions.find_by_version(version.to_i) if version
98 98 result ||= content
99 99 result
100 100 end
101 101
102 102 def diff(version_to=nil, version_from=nil)
103 103 version_to = version_to ? version_to.to_i : self.content.version
104 104 version_from = version_from ? version_from.to_i : version_to - 1
105 105 version_to, version_from = version_from, version_to unless version_from < version_to
106 106
107 107 content_to = content.versions.find_by_version(version_to)
108 108 content_from = content.versions.find_by_version(version_from)
109 109
110 110 (content_to && content_from) ? WikiDiff.new(content_to, content_from) : nil
111 111 end
112 112
113 113 def annotate(version=nil)
114 114 version = version ? version.to_i : self.content.version
115 115 c = content.versions.find_by_version(version)
116 116 c ? WikiAnnotate.new(c) : nil
117 117 end
118 118
119 119 def self.pretty_title(str)
120 120 (str && str.is_a?(String)) ? str.tr('_', ' ') : str
121 121 end
122 122
123 123 def project
124 124 wiki.project
125 125 end
126 126
127 127 def text
128 128 content.text if content
129 129 end
130 130
131 131 def updated_on
132 132 unless @updated_on
133 133 if time = read_attribute(:updated_on)
134 134 # content updated_on was eager loaded with the page
135 135 @updated_on = Time.parse(time) rescue nil
136 136 else
137 137 @updated_on = content && content.updated_on
138 138 end
139 139 end
140 140 @updated_on
141 141 end
142 142
143 143 # Returns true if usr is allowed to edit the page, otherwise false
144 144 def editable_by?(usr)
145 145 !protected? || usr.allowed_to?(:protect_wiki_pages, wiki.project)
146 146 end
147 147
148 148 def attachments_deletable?(usr=User.current)
149 149 editable_by?(usr) && super(usr)
150 150 end
151 151
152 152 def parent_title
153 153 @parent_title || (self.parent && self.parent.pretty_title)
154 154 end
155 155
156 156 def parent_title=(t)
157 157 @parent_title = t
158 158 parent_page = t.blank? ? nil : self.wiki.find_page(t)
159 159 self.parent = parent_page
160 160 end
161 161
162 162 protected
163 163
164 164 def validate
165 165 errors.add(:parent_title, :invalid) if !@parent_title.blank? && parent.nil?
166 166 errors.add(:parent_title, :circular_dependency) if parent && (parent == self || parent.ancestors.include?(self))
167 167 errors.add(:parent_title, :not_same_project) if parent && (parent.wiki_id != wiki_id)
168 168 end
169 169 end
170 170
171 171 class WikiDiff < Redmine::Helpers::Diff
172 172 attr_reader :content_to, :content_from
173 173
174 174 def initialize(content_to, content_from)
175 175 @content_to = content_to
176 176 @content_from = content_from
177 177 super(content_to.text, content_from.text)
178 178 end
179 179 end
180 180
181 181 class WikiAnnotate
182 182 attr_reader :lines, :content
183 183
184 184 def initialize(content)
185 185 @content = content
186 186 current = content
187 187 current_lines = current.text.split(/\r?\n/)
188 188 @lines = current_lines.collect {|t| [nil, nil, t]}
189 189 positions = []
190 190 current_lines.size.times {|i| positions << i}
191 191 while (current.previous)
192 192 d = current.previous.text.split(/\r?\n/).diff(current.text.split(/\r?\n/)).diffs.flatten
193 193 d.each_slice(3) do |s|
194 194 sign, line = s[0], s[1]
195 195 if sign == '+' && positions[line] && positions[line] != -1
196 196 if @lines[positions[line]][0].nil?
197 197 @lines[positions[line]][0] = current.version
198 198 @lines[positions[line]][1] = current.author
199 199 end
200 200 end
201 201 end
202 202 d.each_slice(3) do |s|
203 203 sign, line = s[0], s[1]
204 204 if sign == '-'
205 205 positions.insert(line, -1)
206 206 else
207 207 positions[line] = nil
208 208 end
209 209 end
210 210 positions.compact!
211 211 # Stop if every line is annotated
212 212 break unless @lines.detect { |line| line[0].nil? }
213 213 current = current.previous
214 214 end
215 @lines.each { |line| line[0] ||= current.version }
215 @lines.each { |line|
216 line[0] ||= current.version
217 # if the last known version is > 1 (eg. history was cleared), we don't know the author
218 line[1] ||= current.author if current.version == 1
219 }
216 220 end
217 221 end
@@ -1,511 +1,521
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 58 def test_show_redirected_page
59 59 WikiRedirect.create!(:wiki_id => 1, :title => 'Old_title', :redirects_to => 'Another_page')
60 60
61 61 get :show, :project_id => 'ecookbook', :id => 'Old_title'
62 62 assert_redirected_to '/projects/ecookbook/wiki/Another_page'
63 63 end
64 64
65 65 def test_show_with_sidebar
66 66 page = Project.find(1).wiki.pages.new(:title => 'Sidebar')
67 67 page.content = WikiContent.new(:text => 'Side bar content for test_show_with_sidebar')
68 68 page.save!
69 69
70 70 get :show, :project_id => 1, :id => 'Another_page'
71 71 assert_response :success
72 72 assert_tag :tag => 'div', :attributes => {:id => 'sidebar'},
73 73 :content => /Side bar content for test_show_with_sidebar/
74 74 end
75 75
76 76 def test_show_unexistent_page_without_edit_right
77 77 get :show, :project_id => 1, :id => 'Unexistent page'
78 78 assert_response 404
79 79 end
80 80
81 81 def test_show_unexistent_page_with_edit_right
82 82 @request.session[:user_id] = 2
83 83 get :show, :project_id => 1, :id => 'Unexistent page'
84 84 assert_response :success
85 85 assert_template 'edit'
86 86 end
87 87
88 88 def test_create_page
89 89 @request.session[:user_id] = 2
90 90 put :update, :project_id => 1,
91 91 :id => 'New page',
92 92 :content => {:comments => 'Created the page',
93 93 :text => "h1. New page\n\nThis is a new page",
94 94 :version => 0}
95 95 assert_redirected_to :action => 'show', :project_id => 'ecookbook', :id => 'New_page'
96 96 page = Project.find(1).wiki.find_page('New page')
97 97 assert !page.new_record?
98 98 assert_not_nil page.content
99 99 assert_equal 'Created the page', page.content.comments
100 100 end
101 101
102 102 def test_create_page_with_attachments
103 103 @request.session[:user_id] = 2
104 104 assert_difference 'WikiPage.count' do
105 105 assert_difference 'Attachment.count' do
106 106 put :update, :project_id => 1,
107 107 :id => 'New page',
108 108 :content => {:comments => 'Created the page',
109 109 :text => "h1. New page\n\nThis is a new page",
110 110 :version => 0},
111 111 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
112 112 end
113 113 end
114 114 page = Project.find(1).wiki.find_page('New page')
115 115 assert_equal 1, page.attachments.count
116 116 assert_equal 'testfile.txt', page.attachments.first.filename
117 117 end
118 118
119 119 def test_update_page
120 120 @request.session[:user_id] = 2
121 121 assert_no_difference 'WikiPage.count' do
122 122 assert_no_difference 'WikiContent.count' do
123 123 assert_difference 'WikiContent::Version.count' do
124 124 put :update, :project_id => 1,
125 125 :id => 'Another_page',
126 126 :content => {
127 127 :comments => "my comments",
128 128 :text => "edited",
129 129 :version => 1
130 130 }
131 131 end
132 132 end
133 133 end
134 134 assert_redirected_to '/projects/ecookbook/wiki/Another_page'
135 135
136 136 page = Wiki.find(1).pages.find_by_title('Another_page')
137 137 assert_equal "edited", page.content.text
138 138 assert_equal 2, page.content.version
139 139 assert_equal "my comments", page.content.comments
140 140 end
141 141
142 142 def test_update_page_with_failure
143 143 @request.session[:user_id] = 2
144 144 assert_no_difference 'WikiPage.count' do
145 145 assert_no_difference 'WikiContent.count' do
146 146 assert_no_difference 'WikiContent::Version.count' do
147 147 put :update, :project_id => 1,
148 148 :id => 'Another_page',
149 149 :content => {
150 150 :comments => 'a' * 300, # failure here, comment is too long
151 151 :text => 'edited',
152 152 :version => 1
153 153 }
154 154 end
155 155 end
156 156 end
157 157 assert_response :success
158 158 assert_template 'edit'
159 159
160 160 assert_error_tag :descendant => {:content => /Comment is too long/}
161 161 assert_tag :tag => 'textarea', :attributes => {:id => 'content_text'}, :content => 'edited'
162 162 assert_tag :tag => 'input', :attributes => {:id => 'content_version', :value => '1'}
163 163 end
164 164
165 165 def test_update_stale_page_should_not_raise_an_error
166 166 @request.session[:user_id] = 2
167 167 c = Wiki.find(1).find_page('Another_page').content
168 168 c.text = 'Previous text'
169 169 c.save!
170 170 assert_equal 2, c.version
171 171
172 172 assert_no_difference 'WikiPage.count' do
173 173 assert_no_difference 'WikiContent.count' do
174 174 assert_no_difference 'WikiContent::Version.count' do
175 175 put :update, :project_id => 1,
176 176 :id => 'Another_page',
177 177 :content => {
178 178 :comments => 'My comments',
179 179 :text => 'Text should not be lost',
180 180 :version => 1
181 181 }
182 182 end
183 183 end
184 184 end
185 185 assert_response :success
186 186 assert_template 'edit'
187 187 assert_tag :div,
188 188 :attributes => { :class => /error/ },
189 189 :content => /Data has been updated by another user/
190 190 assert_tag 'textarea',
191 191 :attributes => { :name => 'content[text]' },
192 192 :content => /Text should not be lost/
193 193 assert_tag 'input',
194 194 :attributes => { :name => 'content[comments]', :value => 'My comments' }
195 195
196 196 c.reload
197 197 assert_equal 'Previous text', c.text
198 198 assert_equal 2, c.version
199 199 end
200 200
201 201 def test_preview
202 202 @request.session[:user_id] = 2
203 203 xhr :post, :preview, :project_id => 1, :id => 'CookBook_documentation',
204 204 :content => { :comments => '',
205 205 :text => 'this is a *previewed text*',
206 206 :version => 3 }
207 207 assert_response :success
208 208 assert_template 'common/_preview'
209 209 assert_tag :tag => 'strong', :content => /previewed text/
210 210 end
211 211
212 212 def test_preview_new_page
213 213 @request.session[:user_id] = 2
214 214 xhr :post, :preview, :project_id => 1, :id => 'New page',
215 215 :content => { :text => 'h1. New page',
216 216 :comments => '',
217 217 :version => 0 }
218 218 assert_response :success
219 219 assert_template 'common/_preview'
220 220 assert_tag :tag => 'h1', :content => /New page/
221 221 end
222 222
223 223 def test_history
224 224 get :history, :project_id => 1, :id => 'CookBook_documentation'
225 225 assert_response :success
226 226 assert_template 'history'
227 227 assert_not_nil assigns(:versions)
228 228 assert_equal 3, assigns(:versions).size
229 229 assert_select "input[type=submit][name=commit]"
230 230 end
231 231
232 232 def test_history_with_one_version
233 233 get :history, :project_id => 1, :id => 'Another_page'
234 234 assert_response :success
235 235 assert_template 'history'
236 236 assert_not_nil assigns(:versions)
237 237 assert_equal 1, assigns(:versions).size
238 238 assert_select "input[type=submit][name=commit]", false
239 239 end
240 240
241 241 def test_diff
242 242 get :diff, :project_id => 1, :id => 'CookBook_documentation', :version => 2, :version_from => 1
243 243 assert_response :success
244 244 assert_template 'diff'
245 245 assert_tag :tag => 'span', :attributes => { :class => 'diff_in'},
246 246 :content => /updated/
247 247 end
248 248
249 249 def test_annotate
250 250 get :annotate, :project_id => 1, :id => 'CookBook_documentation', :version => 2
251 251 assert_response :success
252 252 assert_template 'annotate'
253
253 254 # Line 1
254 assert_tag :tag => 'tr', :child => { :tag => 'th', :attributes => {:class => 'line-num'}, :content => '1' },
255 :child => { :tag => 'td', :attributes => {:class => 'author'}, :content => /John Smith/ },
256 :child => { :tag => 'td', :content => /h1\. CookBook documentation/ }
257 # Line 2
258 assert_tag :tag => 'tr', :child => { :tag => 'th', :attributes => {:class => 'line-num'}, :content => '2' },
259 :child => { :tag => 'td', :attributes => {:class => 'author'}, :content => /redMine Admin/ },
260 :child => { :tag => 'td', :content => /Some updated \[\[documentation\]\] here/ }
255 assert_tag :tag => 'tr', :child => {
256 :tag => 'th', :attributes => {:class => 'line-num'}, :content => '1', :sibling => {
257 :tag => 'td', :attributes => {:class => 'author'}, :content => /John Smith/, :sibling => {
258 :tag => 'td', :content => /h1\. CookBook documentation/
259 }
260 }
261 }
262
263 # Line 5
264 assert_tag :tag => 'tr', :child => {
265 :tag => 'th', :attributes => {:class => 'line-num'}, :content => '5', :sibling => {
266 :tag => 'td', :attributes => {:class => 'author'}, :content => /redMine Admin/, :sibling => {
267 :tag => 'td', :content => /Some updated \[\[documentation\]\] here/
268 }
269 }
270 }
261 271 end
262 272
263 273 def test_get_rename
264 274 @request.session[:user_id] = 2
265 275 get :rename, :project_id => 1, :id => 'Another_page'
266 276 assert_response :success
267 277 assert_template 'rename'
268 278 assert_tag 'option',
269 279 :attributes => {:value => ''},
270 280 :content => '',
271 281 :parent => {:tag => 'select', :attributes => {:name => 'wiki_page[parent_id]'}}
272 282 assert_no_tag 'option',
273 283 :attributes => {:selected => 'selected'},
274 284 :parent => {:tag => 'select', :attributes => {:name => 'wiki_page[parent_id]'}}
275 285 end
276 286
277 287 def test_get_rename_child_page
278 288 @request.session[:user_id] = 2
279 289 get :rename, :project_id => 1, :id => 'Child_1'
280 290 assert_response :success
281 291 assert_template 'rename'
282 292 assert_tag 'option',
283 293 :attributes => {:value => ''},
284 294 :content => '',
285 295 :parent => {:tag => 'select', :attributes => {:name => 'wiki_page[parent_id]'}}
286 296 assert_tag 'option',
287 297 :attributes => {:value => '2', :selected => 'selected'},
288 298 :content => /Another page/,
289 299 :parent => {
290 300 :tag => 'select',
291 301 :attributes => {:name => 'wiki_page[parent_id]'}
292 302 }
293 303 end
294 304
295 305 def test_rename_with_redirect
296 306 @request.session[:user_id] = 2
297 307 post :rename, :project_id => 1, :id => 'Another_page',
298 308 :wiki_page => { :title => 'Another renamed page',
299 309 :redirect_existing_links => 1 }
300 310 assert_redirected_to :action => 'show', :project_id => 'ecookbook', :id => 'Another_renamed_page'
301 311 wiki = Project.find(1).wiki
302 312 # Check redirects
303 313 assert_not_nil wiki.find_page('Another page')
304 314 assert_nil wiki.find_page('Another page', :with_redirect => false)
305 315 end
306 316
307 317 def test_rename_without_redirect
308 318 @request.session[:user_id] = 2
309 319 post :rename, :project_id => 1, :id => 'Another_page',
310 320 :wiki_page => { :title => 'Another renamed page',
311 321 :redirect_existing_links => "0" }
312 322 assert_redirected_to :action => 'show', :project_id => 'ecookbook', :id => 'Another_renamed_page'
313 323 wiki = Project.find(1).wiki
314 324 # Check that there's no redirects
315 325 assert_nil wiki.find_page('Another page')
316 326 end
317 327
318 328 def test_rename_with_parent_assignment
319 329 @request.session[:user_id] = 2
320 330 post :rename, :project_id => 1, :id => 'Another_page',
321 331 :wiki_page => { :title => 'Another page', :redirect_existing_links => "0", :parent_id => '4' }
322 332 assert_redirected_to :action => 'show', :project_id => 'ecookbook', :id => 'Another_page'
323 333 assert_equal WikiPage.find(4), WikiPage.find_by_title('Another_page').parent
324 334 end
325 335
326 336 def test_rename_with_parent_unassignment
327 337 @request.session[:user_id] = 2
328 338 post :rename, :project_id => 1, :id => 'Child_1',
329 339 :wiki_page => { :title => 'Child 1', :redirect_existing_links => "0", :parent_id => '' }
330 340 assert_redirected_to :action => 'show', :project_id => 'ecookbook', :id => 'Child_1'
331 341 assert_nil WikiPage.find_by_title('Child_1').parent
332 342 end
333 343
334 344 def test_destroy_child
335 345 @request.session[:user_id] = 2
336 346 delete :destroy, :project_id => 1, :id => 'Child_1'
337 347 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
338 348 end
339 349
340 350 def test_destroy_parent
341 351 @request.session[:user_id] = 2
342 352 assert_no_difference('WikiPage.count') do
343 353 delete :destroy, :project_id => 1, :id => 'Another_page'
344 354 end
345 355 assert_response :success
346 356 assert_template 'destroy'
347 357 end
348 358
349 359 def test_destroy_parent_with_nullify
350 360 @request.session[:user_id] = 2
351 361 assert_difference('WikiPage.count', -1) do
352 362 delete :destroy, :project_id => 1, :id => 'Another_page', :todo => 'nullify'
353 363 end
354 364 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
355 365 assert_nil WikiPage.find_by_id(2)
356 366 end
357 367
358 368 def test_destroy_parent_with_cascade
359 369 @request.session[:user_id] = 2
360 370 assert_difference('WikiPage.count', -3) do
361 371 delete :destroy, :project_id => 1, :id => 'Another_page', :todo => 'destroy'
362 372 end
363 373 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
364 374 assert_nil WikiPage.find_by_id(2)
365 375 assert_nil WikiPage.find_by_id(5)
366 376 end
367 377
368 378 def test_destroy_parent_with_reassign
369 379 @request.session[:user_id] = 2
370 380 assert_difference('WikiPage.count', -1) do
371 381 delete :destroy, :project_id => 1, :id => 'Another_page', :todo => 'reassign', :reassign_to_id => 1
372 382 end
373 383 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
374 384 assert_nil WikiPage.find_by_id(2)
375 385 assert_equal WikiPage.find(1), WikiPage.find_by_id(5).parent
376 386 end
377 387
378 388 def test_index
379 389 get :index, :project_id => 'ecookbook'
380 390 assert_response :success
381 391 assert_template 'index'
382 392 pages = assigns(:pages)
383 393 assert_not_nil pages
384 394 assert_equal Project.find(1).wiki.pages.size, pages.size
385 395 assert_equal pages.first.content.updated_on, pages.first.updated_on
386 396
387 397 assert_tag :ul, :attributes => { :class => 'pages-hierarchy' },
388 398 :child => { :tag => 'li', :child => { :tag => 'a', :attributes => { :href => '/projects/ecookbook/wiki/CookBook_documentation' },
389 399 :content => 'CookBook documentation' },
390 400 :child => { :tag => 'ul',
391 401 :child => { :tag => 'li',
392 402 :child => { :tag => 'a', :attributes => { :href => '/projects/ecookbook/wiki/Page_with_an_inline_image' },
393 403 :content => 'Page with an inline image' } } } },
394 404 :child => { :tag => 'li', :child => { :tag => 'a', :attributes => { :href => '/projects/ecookbook/wiki/Another_page' },
395 405 :content => 'Another page' } }
396 406 end
397 407
398 408 def test_index_should_include_atom_link
399 409 get :index, :project_id => 'ecookbook'
400 410 assert_tag 'a', :attributes => { :href => '/projects/ecookbook/activity.atom?show_wiki_edits=1'}
401 411 end
402 412
403 413 context "GET :export" do
404 414 context "with an authorized user to export the wiki" do
405 415 setup do
406 416 @request.session[:user_id] = 2
407 417 get :export, :project_id => 'ecookbook'
408 418 end
409 419
410 420 should_respond_with :success
411 421 should_assign_to :pages
412 422 should_respond_with_content_type "text/html"
413 423 should "export all of the wiki pages to a single html file" do
414 424 assert_select "a[name=?]", "CookBook_documentation"
415 425 assert_select "a[name=?]", "Another_page"
416 426 assert_select "a[name=?]", "Page_with_an_inline_image"
417 427 end
418 428
419 429 end
420 430
421 431 context "with an unauthorized user" do
422 432 setup do
423 433 get :export, :project_id => 'ecookbook'
424 434
425 435 should_respond_with :redirect
426 436 should_redirect_to('wiki index') { {:action => 'show', :project_id => @project, :id => nil} }
427 437 end
428 438 end
429 439 end
430 440
431 441 context "GET :date_index" do
432 442 setup do
433 443 get :date_index, :project_id => 'ecookbook'
434 444 end
435 445
436 446 should_respond_with :success
437 447 should_assign_to :pages
438 448 should_assign_to :pages_by_date
439 449 should_render_template 'wiki/date_index'
440 450
441 451 should "include atom link" do
442 452 assert_tag 'a', :attributes => { :href => '/projects/ecookbook/activity.atom?show_wiki_edits=1'}
443 453 end
444 454 end
445 455
446 456 def test_not_found
447 457 get :show, :project_id => 999
448 458 assert_response 404
449 459 end
450 460
451 461 def test_protect_page
452 462 page = WikiPage.find_by_wiki_id_and_title(1, 'Another_page')
453 463 assert !page.protected?
454 464 @request.session[:user_id] = 2
455 465 post :protect, :project_id => 1, :id => page.title, :protected => '1'
456 466 assert_redirected_to :action => 'show', :project_id => 'ecookbook', :id => 'Another_page'
457 467 assert page.reload.protected?
458 468 end
459 469
460 470 def test_unprotect_page
461 471 page = WikiPage.find_by_wiki_id_and_title(1, 'CookBook_documentation')
462 472 assert page.protected?
463 473 @request.session[:user_id] = 2
464 474 post :protect, :project_id => 1, :id => page.title, :protected => '0'
465 475 assert_redirected_to :action => 'show', :project_id => 'ecookbook', :id => 'CookBook_documentation'
466 476 assert !page.reload.protected?
467 477 end
468 478
469 479 def test_show_page_with_edit_link
470 480 @request.session[:user_id] = 2
471 481 get :show, :project_id => 1
472 482 assert_response :success
473 483 assert_template 'show'
474 484 assert_tag :tag => 'a', :attributes => { :href => '/projects/1/wiki/CookBook_documentation/edit' }
475 485 end
476 486
477 487 def test_show_page_without_edit_link
478 488 @request.session[:user_id] = 4
479 489 get :show, :project_id => 1
480 490 assert_response :success
481 491 assert_template 'show'
482 492 assert_no_tag :tag => 'a', :attributes => { :href => '/projects/1/wiki/CookBook_documentation/edit' }
483 493 end
484 494
485 495 def test_edit_unprotected_page
486 496 # Non members can edit unprotected wiki pages
487 497 @request.session[:user_id] = 4
488 498 get :edit, :project_id => 1, :id => 'Another_page'
489 499 assert_response :success
490 500 assert_template 'edit'
491 501 end
492 502
493 503 def test_edit_protected_page_by_nonmember
494 504 # Non members can't edit protected wiki pages
495 505 @request.session[:user_id] = 4
496 506 get :edit, :project_id => 1, :id => 'CookBook_documentation'
497 507 assert_response 403
498 508 end
499 509
500 510 def test_edit_protected_page_by_member
501 511 @request.session[:user_id] = 2
502 512 get :edit, :project_id => 1, :id => 'CookBook_documentation'
503 513 assert_response :success
504 514 assert_template 'edit'
505 515 end
506 516
507 517 def test_history_of_non_existing_page_should_return_404
508 518 get :history, :project_id => 1, :id => 'Unknown_page'
509 519 assert_response 404
510 520 end
511 521 end
General Comments 0
You need to be logged in to leave comments. Login now