Wiki: allows single section edit (#2222).

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@7829 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
Jean-Philippe Lang
2011-11-18 16:25:00 +00:00
parent b38dc9a301
commit 6fc245327c
55 changed files with 440 additions and 41 deletions
+22 -1
View File
@@ -103,4 +103,25 @@ wiki_contents_010:
version: 1
author_id: 1
comments:
wiki_contents_011:
text: |-
h1. Title
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero.
h2. Heading 1
Maecenas sed elit sit amet mi accumsan vestibulum non nec velit. Proin porta tincidunt lorem, consequat rhoncus dolor fermentum in.
Cras ipsum felis, ultrices at porttitor vel, faucibus eu nunc.
h2. Heading 2
Morbi facilisis accumsan orci non pharetra.
updated_on: 2007-03-08 00:18:07 +01:00
page_id: 11
id: 11
version: 3
author_id: 1
comments:
+7
View File
@@ -69,3 +69,10 @@ wiki_pages_010:
wiki_id: 1
protected: false
parent_id:
wiki_pages_011:
created_on: 2007-03-08 00:18:07 +01:00
title: Page_with_sections
id: 11
wiki_id: 1
protected: false
parent_id:
+115
View File
@@ -118,6 +118,44 @@ class WikiControllerTest < ActionController::TestCase
assert_equal 'testfile.txt', page.attachments.first.filename
end
def test_edit_page
@request.session[:user_id] = 2
get :edit, :project_id => 'ecookbook', :id => 'Another_page'
assert_response :success
assert_template 'edit'
assert_tag 'textarea',
:attributes => { :name => 'content[text]' },
:content => WikiPage.find_by_title('Another_page').content.text
end
def test_edit_section
@request.session[:user_id] = 2
get :edit, :project_id => 'ecookbook', :id => 'Page_with_sections', :section => 2
assert_response :success
assert_template 'edit'
page = WikiPage.find_by_title('Page_with_sections')
section, hash = Redmine::WikiFormatting::Textile::Formatter.new(page.content.text).get_section(2)
assert_tag 'textarea',
:attributes => { :name => 'content[text]' },
:content => section
assert_tag 'input',
:attributes => { :name => 'section', :type => 'hidden', :value => '2' }
assert_tag 'input',
:attributes => { :name => 'section_hash', :type => 'hidden', :value => hash }
end
def test_edit_invalid_section_should_respond_with_404
@request.session[:user_id] = 2
get :edit, :project_id => 'ecookbook', :id => 'Page_with_sections', :section => 10
assert_response 404
end
def test_update_page
@request.session[:user_id] = 2
assert_no_difference 'WikiPage.count' do
@@ -200,6 +238,83 @@ class WikiControllerTest < ActionController::TestCase
assert_equal 2, c.version
end
def test_update_section
@request.session[:user_id] = 2
page = WikiPage.find_by_title('Page_with_sections')
section, hash = Redmine::WikiFormatting::Textile::Formatter.new(page.content.text).get_section(2)
text = page.content.text
assert_no_difference 'WikiPage.count' do
assert_no_difference 'WikiContent.count' do
assert_difference 'WikiContent::Version.count' do
put :update, :project_id => 1, :id => 'Page_with_sections',
:content => {
:text => "New section content",
:version => 3
},
:section => 2,
:section_hash => hash
end
end
end
assert_redirected_to '/projects/ecookbook/wiki/Page_with_sections'
assert_equal Redmine::WikiFormatting::Textile::Formatter.new(text).update_section(2, "New section content"), page.reload.content.text
end
def test_update_section_should_allow_stale_page_update
@request.session[:user_id] = 2
page = WikiPage.find_by_title('Page_with_sections')
section, hash = Redmine::WikiFormatting::Textile::Formatter.new(page.content.text).get_section(2)
text = page.content.text
assert_no_difference 'WikiPage.count' do
assert_no_difference 'WikiContent.count' do
assert_difference 'WikiContent::Version.count' do
put :update, :project_id => 1, :id => 'Page_with_sections',
:content => {
:text => "New section content",
:version => 2 # Current version is 3
},
:section => 2,
:section_hash => hash
end
end
end
assert_redirected_to '/projects/ecookbook/wiki/Page_with_sections'
page.reload
assert_equal Redmine::WikiFormatting::Textile::Formatter.new(text).update_section(2, "New section content"), page.content.text
assert_equal 4, page.content.version
end
def test_update_section_should_not_allow_stale_section_update
@request.session[:user_id] = 2
assert_no_difference 'WikiPage.count' do
assert_no_difference 'WikiContent.count' do
assert_no_difference 'WikiContent::Version.count' do
put :update, :project_id => 1, :id => 'Page_with_sections',
:content => {
:comments => 'My comments',
:text => "Text should not be lost",
:version => 3
},
:section => 2,
:section_hash => Digest::MD5.hexdigest("wrong hash")
end
end
end
assert_response :success
assert_template 'edit'
assert_tag :div,
:attributes => { :class => /error/ },
:content => /Data has been updated by another user/
assert_tag 'textarea',
:attributes => { :name => 'content[text]' },
:content => /Text should not be lost/
assert_tag 'input',
:attributes => { :name => 'content[comments]', :value => 'My comments' }
end
def test_preview
@request.session[:user_id] = 2
xhr :post, :preview, :project_id => 1, :id => 'CookBook_documentation',
@@ -16,6 +16,7 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.expand_path('../../../../../test_helper', __FILE__)
require 'digest/md5'
class Redmine::WikiFormatting::TextileFormatterTest < ActionView::TestCase
@@ -203,6 +204,101 @@ EXPECTED
expected = '<p><img src="/images/comment.png&quot;onclick=&amp;#x61;&amp;#x6c;&amp;#x65;&amp;#x72;&amp;#x74;&amp;#x28;&amp;#x27;&amp;#x58;&amp;#x53;&amp;#x53;&amp;#x27;&amp;#x29;;&amp;#x22;" alt="" /></p>'
assert_equal expected.gsub(%r{\s+}, ''), to_html(raw).gsub(%r{\s+}, '')
end
STR_WITHOUT_PRE = [
# 0
"h1. Title
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero.",
# 1
"h2. Heading 2
Maecenas sed elit sit amet mi accumsan vestibulum non nec velit. Proin porta tincidunt lorem, consequat rhoncus dolor fermentum in.
Cras ipsum felis, ultrices at porttitor vel, faucibus eu nunc.",
# 2
"h2. Heading 2
Morbi facilisis accumsan orci non pharetra.
h3. Heading 3
Nulla nunc nisi, egestas in ornare vel, posuere ac libero.",
# 3
"h3. Heading 3
Praesent eget turpis nibh, a lacinia nulla.",
# 4
"h2. Heading 2
Ut rhoncus elementum adipiscing."]
TEXT_WITHOUT_PRE = STR_WITHOUT_PRE.join("\n\n").freeze
def test_get_section_should_return_the_requested_section_and_its_hash
assert_section_with_hash STR_WITHOUT_PRE[1], TEXT_WITHOUT_PRE, 2
assert_section_with_hash STR_WITHOUT_PRE[2..3].join("\n\n"), TEXT_WITHOUT_PRE, 3
assert_section_with_hash STR_WITHOUT_PRE[3], TEXT_WITHOUT_PRE, 5
assert_section_with_hash STR_WITHOUT_PRE[4], TEXT_WITHOUT_PRE, 6
assert_section_with_hash '', TEXT_WITHOUT_PRE, 0
assert_section_with_hash '', TEXT_WITHOUT_PRE, 10
end
def test_update_section_should_update_the_requested_section
replacement = "New text"
assert_equal [STR_WITHOUT_PRE[0], replacement, STR_WITHOUT_PRE[2..4]].flatten.join("\n\n"), @formatter.new(TEXT_WITHOUT_PRE).update_section(2, replacement)
assert_equal [STR_WITHOUT_PRE[0..1], replacement, STR_WITHOUT_PRE[4]].flatten.join("\n\n"), @formatter.new(TEXT_WITHOUT_PRE).update_section(3, replacement)
assert_equal [STR_WITHOUT_PRE[0..2], replacement, STR_WITHOUT_PRE[4]].flatten.join("\n\n"), @formatter.new(TEXT_WITHOUT_PRE).update_section(5, replacement)
assert_equal [STR_WITHOUT_PRE[0..3], replacement].flatten.join("\n\n"), @formatter.new(TEXT_WITHOUT_PRE).update_section(6, replacement)
assert_equal TEXT_WITHOUT_PRE, @formatter.new(TEXT_WITHOUT_PRE).update_section(0, replacement)
assert_equal TEXT_WITHOUT_PRE, @formatter.new(TEXT_WITHOUT_PRE).update_section(10, replacement)
end
def test_update_section_with_hash_should_update_the_requested_section
replacement = "New text"
assert_equal [STR_WITHOUT_PRE[0], replacement, STR_WITHOUT_PRE[2..4]].flatten.join("\n\n"),
@formatter.new(TEXT_WITHOUT_PRE).update_section(2, replacement, Digest::MD5.hexdigest(STR_WITHOUT_PRE[1]))
end
def test_update_section_with_wrong_hash_should_raise_an_error
assert_raise Redmine::WikiFormatting::StaleSectionError do
@formatter.new(TEXT_WITHOUT_PRE).update_section(2, "New text", Digest::MD5.hexdigest("Old text"))
end
end
STR_WITH_PRE = [
# 0
"h1. Title
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero.",
# 1
"h2. Heading 2
Morbi facilisis accumsan orci non pharetra.
<pre>
Pre Content:
h2. Inside pre
Morbi facilisis accumsan orci non pharetra.
</pre>",
# 2
"h3. Heading 3
Nulla nunc nisi, egestas in ornare vel, posuere ac libero."]
def test_get_section_should_ignore_pre_content
text = STR_WITH_PRE.join("\n\n")
assert_section_with_hash STR_WITH_PRE[1..2].join("\n\n"), text, 2
assert_section_with_hash STR_WITH_PRE[2], text, 3
end
private
@@ -215,4 +311,13 @@ EXPECTED
def to_html(text)
@formatter.new(text).to_html
end
def assert_section_with_hash(expected, text, index)
result = @formatter.new(text).get_section(index)
assert_kind_of Array, result
assert_equal 2, result.size
assert_equal expected, result.first, "section content did not match"
assert_equal Digest::MD5.hexdigest(expected), result.last, "section hash did not match"
end
end