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:
Vendored
+22
-1
@@ -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:
|
||||
|
||||
|
||||
Vendored
+7
@@ -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:
|
||||
|
||||
@@ -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"onclick=&#x61;&#x6c;&#x65;&#x72;&#x74;&#x28;&#x27;&#x58;&#x53;&#x53;&#x27;&#x29;;&#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
|
||||
|
||||
Reference in New Issue
Block a user