cd5c19e530
Make remove_orphaned_pages work in a proxied situation. Also, "fix" a busted functional test. I'm not happy with this one. We're enforcing plain-text titles (which, I think, is the correct thing to do), but sending them as type="html", which then requires double-encoding.
947 lines
33 KiB
Ruby
Executable file
947 lines
33 KiB
Ruby
Executable file
#!/usr/bin/env ruby
|
|
|
|
# Uncomment the line below to enable pdflatex tests; don't forget to comment them again
|
|
# commiting to SVN
|
|
# $INSTIKI_TEST_PDFLATEX = true
|
|
|
|
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
|
require 'wiki_controller'
|
|
require 'rexml/document'
|
|
require 'tempfile'
|
|
require 'zip/zipfilesystem'
|
|
|
|
# Raise errors beyond the default web-based presentation
|
|
class WikiController; def rescue_action(e) logger.error(e); raise e end; end
|
|
|
|
class WikiControllerTest < Test::Unit::TestCase
|
|
fixtures :webs, :pages, :revisions, :system, :wiki_references
|
|
|
|
def setup
|
|
@controller = WikiController.new
|
|
@request = ActionController::TestRequest.new
|
|
@response = ActionController::TestResponse.new
|
|
class << @request.session
|
|
attr_accessor :dbman
|
|
end
|
|
# simulate a cookie session store
|
|
@request.session.dbman = FakeSessionDbMan
|
|
@wiki = Wiki.new
|
|
@web = webs(:test_wiki)
|
|
@home = @page = pages(:home_page)
|
|
@oak = pages(:oak)
|
|
@elephant = pages(:elephant)
|
|
end
|
|
|
|
def test_authenticate
|
|
set_web_property :password, 'pswd'
|
|
|
|
get :authenticate, :web => 'wiki1', :password => 'pswd'
|
|
assert_redirected_to :web => 'wiki1', :action => 'show', :id => 'HomePage'
|
|
assert_equal ['pswd'], @response.cookies['wiki1']
|
|
end
|
|
|
|
def test_authenticate_wrong_password
|
|
set_web_property :password, 'pswd'
|
|
|
|
r = process('authenticate', 'web' => 'wiki1', 'password' => 'wrong password')
|
|
assert_redirected_to :action => 'login', :web => 'wiki1'
|
|
assert_nil r.cookies['web_address']
|
|
end
|
|
|
|
def test_authors
|
|
@wiki.write_page('wiki1', 'BreakSortingOrder',
|
|
"This page breaks the accidentally correct sorting order of authors",
|
|
Time.now, Author.new('BreakingTheOrder', '127.0.0.2'), test_renderer)
|
|
|
|
r = process('authors', 'web' => 'wiki1')
|
|
|
|
assert_response(:success)
|
|
assert_equal %w(AnAuthor BreakingTheOrder DavidHeinemeierHansson Guest Me TreeHugger),
|
|
r.template_objects['authors']
|
|
page_names_by_author = r.template_objects['page_names_by_author']
|
|
assert_equal r.template_objects['authors'], page_names_by_author.keys.sort
|
|
assert_equal %w(FirstPage HomePage), page_names_by_author['DavidHeinemeierHansson']
|
|
end
|
|
|
|
def test_cancel_edit
|
|
@oak.lock(Time.now, 'Locky')
|
|
assert @oak.locked?(Time.now)
|
|
|
|
r = process('cancel_edit', 'web' => 'wiki1', 'id' => 'Oak')
|
|
|
|
assert_redirected_to :action => 'show', :id => 'Oak'
|
|
assert !Page.find(@oak.id).locked?(Time.now)
|
|
end
|
|
|
|
def test_edit
|
|
r = process 'edit', 'web' => 'wiki1', 'id' => 'HomePage'
|
|
assert_response(:success)
|
|
assert_equal @wiki.read_page('wiki1', 'HomePage'), r.template_objects['page']
|
|
end
|
|
|
|
def test_edit_page_locked_page
|
|
@home.lock(Time.now, 'Locky')
|
|
process 'edit', 'web' => 'wiki1', 'id' => 'HomePage'
|
|
assert_redirected_to :action => 'locked'
|
|
end
|
|
|
|
def test_edit_page_break_lock
|
|
@home.lock(Time.now, 'Locky')
|
|
process 'edit', 'web' => 'wiki1', 'id' => 'HomePage', 'break_lock' => 'y'
|
|
assert_response(:success)
|
|
@home = Page.find(@home.id)
|
|
assert @home.locked?(Time.now)
|
|
end
|
|
|
|
def test_edit_unknown_page
|
|
process 'edit', 'web' => 'wiki1', 'id' => 'UnknownPage', 'break_lock' => 'y'
|
|
assert_redirected_to :controller => 'wiki', :action => 'show', :web => 'wiki1',
|
|
:id => 'HomePage'
|
|
end
|
|
|
|
def test_edit_page_with_special_symbols
|
|
@wiki.write_page('wiki1', 'With : Special /> symbols',
|
|
'This page has special symbols in the name', Time.now, Author.new('Special', '127.0.0.3'),
|
|
test_renderer)
|
|
|
|
r = process 'edit', 'web' => 'wiki1', 'id' => 'With : Special /> symbols'
|
|
assert_response(:success)
|
|
xml = REXML::Document.new(r.body)
|
|
form = REXML::XPath.first(xml, '//form')
|
|
assert_equal '/wiki1/save/With+%3A+Special+%2F%3E+symbols', form.attributes['action']
|
|
end
|
|
|
|
def test_export_html
|
|
# rollback homepage to a version that is easier to match
|
|
@home.rollback(0, Time.now, 'Rick', test_renderer)
|
|
r = process 'export_html', 'web' => 'wiki1'
|
|
|
|
assert_response(:success, bypass_body_parsing = true)
|
|
assert_equal 'application/zip', r.headers['type']
|
|
assert_match /attachment; filename="wiki1-html-\d\d\d\d-\d\d-\d\d-\d\d-\d\d-\d\d.zip"/,
|
|
r.headers['Content-Disposition']
|
|
assert_equal 'PK', r.body[0..1], 'Content is not a zip file'
|
|
|
|
# Tempfile doesn't know how to open files with binary flag, hence the two-step process
|
|
Tempfile.open('instiki_export_file') { |f| @tempfile_path = f.path }
|
|
begin
|
|
File.open(@tempfile_path, 'wb') { |f| f.write(r.body); @exported_file = f.path }
|
|
Zip::ZipFile.open(@exported_file) do |zip|
|
|
assert_equal %w(Elephant.html FirstPage.html HomePage.html MyWay.html NoWikiWord.html Oak.html SmartEngine.html ThatWay.html index.html), zip.dir.entries('.').sort
|
|
assert_match /.*<html .*All about elephants.*<\/html>/,
|
|
zip.file.read('Elephant.html').gsub(/\s+/, ' ')
|
|
assert_match /.*<html .*All about oak.*<\/html>/,
|
|
zip.file.read('Oak.html').gsub(/\s+/, ' ')
|
|
assert_match /.*<html .*First revision of the.*HomePage.*end.*<\/html>/,
|
|
zip.file.read('HomePage.html').gsub(/\s+/, ' ')
|
|
assert_equal '<html><head><META HTTP-EQUIV="Refresh" CONTENT="0;URL=HomePage.html"></head></html> ', zip.file.read('index.html').gsub(/\s+/, ' ')
|
|
end
|
|
ensure
|
|
File.delete(@tempfile_path) if File.exist?(@tempfile_path)
|
|
end
|
|
end
|
|
|
|
def test_export_html_no_layout
|
|
r = process 'export_html', 'web' => 'wiki1', 'layout' => 'no'
|
|
|
|
assert_response(:success, bypass_body_parsing = true)
|
|
assert_equal 'application/zip', r.headers['type']
|
|
assert_match /attachment; filename="wiki1-html-\d\d\d\d-\d\d-\d\d-\d\d-\d\d-\d\d.zip"/,
|
|
r.headers['Content-Disposition']
|
|
assert_equal 'PK', r.body[0..1], 'Content is not a zip file'
|
|
end
|
|
|
|
def test_export_markup
|
|
r = process 'export_markup', 'web' => 'wiki1'
|
|
|
|
assert_response(:success, bypass_body_parsing = true)
|
|
assert_equal 'application/zip', r.headers['type']
|
|
assert_match /attachment; filename="wiki1-markdownMML-\d\d\d\d-\d\d-\d\d-\d\d-\d\d-\d\d.zip"/,
|
|
r.headers['Content-Disposition']
|
|
assert_equal 'PK', r.body[0..1], 'Content is not a zip file'
|
|
end
|
|
|
|
|
|
if ENV['INSTIKI_TEST_LATEX'] or defined? $INSTIKI_TEST_PDFLATEX
|
|
|
|
# def test_export_pdf
|
|
# r = process 'export_pdf', 'web' => 'wiki1'
|
|
# assert_response(:success, bypass_body_parsing = true)
|
|
# assert_equal 'application/pdf', r.headers['type']
|
|
# assert_match /attachment; filename="wiki1-tex-\d\d\d\d-\d\d-\d\d-\d\d-\d\d-\d\d.pdf"/,
|
|
# r.headers['Content-Disposition']
|
|
# assert_equal '%PDF', r.body[0..3]
|
|
# assert_equal "EOF\n", r.body[-4..-1]
|
|
# end
|
|
|
|
else
|
|
puts 'Warning: tests involving pdflatex are very slow, therefore they are disabled by default.'
|
|
puts ' Set environment variable INSTIKI_TEST_PDFLATEX or global Ruby variable'
|
|
puts ' $INSTIKI_TEST_PDFLATEX to enable them.'
|
|
end
|
|
|
|
# def test_export_tex
|
|
# r = process 'export_tex', 'web' => 'wiki1'
|
|
#
|
|
# assert_response(:success, bypass_body_parsing = true)
|
|
# assert_equal 'application/octet-stream', r.headers['type']
|
|
# assert_match /attachment; filename="wiki1-tex-\d\d\d\d-\d\d-\d\d-\d\d-\d\d-\d\d.tex"/,
|
|
# r.headers['Content-Disposition']
|
|
# assert_equal '\documentclass', r.body[0..13], 'Content is not a TeX file'
|
|
# end
|
|
|
|
def test_feeds
|
|
process('feeds', 'web' => 'wiki1')
|
|
end
|
|
|
|
def test_index
|
|
# delete extra web fixture
|
|
webs(:instiki).destroy
|
|
process('index')
|
|
assert_redirected_to :web => 'wiki1', :action => 'show', :id => 'HomePage'
|
|
end
|
|
|
|
def test_index_multiple_webs
|
|
@wiki.create_web('Test Wiki 2', 'wiki2')
|
|
process('index')
|
|
assert_redirected_to :action => 'web_list'
|
|
end
|
|
|
|
def test_index_multiple_webs_web_explicit
|
|
@wiki.create_web('Test Wiki 2', 'wiki2')
|
|
process('index', 'web' => 'wiki2')
|
|
assert_redirected_to :web => 'wiki2', :action => 'show', :id => 'HomePage'
|
|
end
|
|
|
|
def test_index_wiki_not_initialized
|
|
use_blank_wiki
|
|
process('index')
|
|
assert_redirected_to :controller => 'admin', :action => 'create_system'
|
|
end
|
|
|
|
|
|
def test_list
|
|
r = process('list', 'web' => 'wiki1')
|
|
|
|
assert_equal ['animals', 'trees'], r.template_objects['categories']
|
|
assert_nil r.template_objects['category']
|
|
assert_equal [@elephant, pages(:first_page), @home, pages(:my_way), pages(:no_wiki_word),
|
|
@oak, pages(:smart_engine), pages(:that_way)],
|
|
r.template_objects['pages_in_category']
|
|
end
|
|
|
|
|
|
def test_locked
|
|
@home.lock(Time.now, 'Locky')
|
|
r = process('locked', 'web' => 'wiki1', 'id' => 'HomePage')
|
|
assert_response(:success)
|
|
assert_equal @home, r.template_objects['page']
|
|
end
|
|
|
|
|
|
def test_login
|
|
r = process 'login', 'web' => 'wiki1'
|
|
assert_response(:success)
|
|
# this action goes straight to the templates
|
|
end
|
|
|
|
|
|
def test_new
|
|
r = process('new', 'id' => 'NewPage', 'web' => 'wiki1')
|
|
assert_response(:success)
|
|
assert_equal 'AnonymousCoward', r.template_objects['author']
|
|
assert_equal 'NewPage', r.template_objects['page_name']
|
|
end
|
|
|
|
|
|
if ENV['INSTIKI_TEST_LATEX'] or defined? $INSTIKI_TEST_PDFLATEX
|
|
|
|
# def test_pdf
|
|
# assert RedClothForTex.available?, 'Cannot do test_pdf when pdflatex is not available'
|
|
# r = process('pdf', 'web' => 'wiki1', 'id' => 'HomePage')
|
|
# assert_response(:success, bypass_body_parsing = true)
|
|
#
|
|
# assert_equal '%PDF', r.body[0..3]
|
|
# assert_equal "EOF\n", r.body[-4..-1]
|
|
#
|
|
# assert_equal 'application/pdf', r.headers['type']
|
|
# assert_match /attachment; filename="HomePage-wiki1-\d\d\d\d-\d\d-\d\d-\d\d-\d\d-\d\d.pdf"/,
|
|
# r.headers['Content-Disposition']
|
|
# end
|
|
|
|
end
|
|
|
|
|
|
def test_print
|
|
r = process('print', 'web' => 'wiki1', 'id' => 'HomePage')
|
|
|
|
assert_response(:success)
|
|
assert_equal :show, r.template_objects['link_mode']
|
|
end
|
|
|
|
|
|
def test_published
|
|
set_web_property :published, true
|
|
|
|
r = process('published', 'web' => 'wiki1', 'id' => 'HomePage')
|
|
|
|
assert_response(:success)
|
|
assert_equal @home, r.template_objects['page']
|
|
end
|
|
|
|
|
|
def test_published_web_not_published
|
|
set_web_property :published, false
|
|
|
|
r = process('published', 'web' => 'wiki1', 'id' => 'HomePage')
|
|
|
|
assert_response :missing
|
|
end
|
|
|
|
def test_published_should_render_homepage_if_no_page_specified
|
|
set_web_property :published, true
|
|
|
|
r = process('published', 'web' => 'wiki1')
|
|
|
|
assert_response(:success)
|
|
assert_equal @home, r.template_objects['page']
|
|
end
|
|
|
|
|
|
def test_recently_revised
|
|
r = process('recently_revised', 'web' => 'wiki1')
|
|
assert_response(:success)
|
|
|
|
assert_equal %w(animals trees), r.template_objects['categories']
|
|
assert_nil r.template_objects['category']
|
|
all_pages = @elephant, pages(:first_page), @home, pages(:my_way), pages(:no_wiki_word),
|
|
@oak, pages(:smart_engine), pages(:that_way)
|
|
assert_equal all_pages, r.template_objects['pages_in_category']
|
|
|
|
pages_by_day = r.template_objects['pages_by_day']
|
|
assert_not_nil pages_by_day
|
|
pages_by_day_size = pages_by_day.keys.inject(0) { |sum, day| sum + pages_by_day[day].size }
|
|
assert_equal all_pages.size, pages_by_day_size
|
|
all_pages.each do |page|
|
|
day = Date.new(page.revised_at.year, page.revised_at.month, page.revised_at.day)
|
|
assert pages_by_day[day].include?(page)
|
|
end
|
|
|
|
assert_equal 'the web', r.template_objects['set_name']
|
|
end
|
|
|
|
def test_recently_revised_with_categorized_page
|
|
page2 = @wiki.write_page('wiki1', 'Page2',
|
|
"Page2 contents.\n" +
|
|
"category: categorized",
|
|
Time.now, Author.new('AnotherAuthor', '127.0.0.2'), test_renderer)
|
|
|
|
r = process('recently_revised', 'web' => 'wiki1')
|
|
assert_response(:success)
|
|
|
|
assert_equal %w(animals categorized trees), r.template_objects['categories']
|
|
# no category is specified in params
|
|
assert_nil r.template_objects['category']
|
|
assert_equal [@elephant, pages(:first_page), @home, pages(:my_way), pages(:no_wiki_word), @oak, page2, pages(:smart_engine), pages(:that_way)], r.template_objects['pages_in_category'],
|
|
"Pages are not as expected: " +
|
|
r.template_objects['pages_in_category'].map {|p| p.name}.inspect
|
|
assert_equal 'the web', r.template_objects['set_name']
|
|
end
|
|
|
|
def test_recently_revised_with_categorized_page_multiple_categories
|
|
r = process('recently_revised', 'web' => 'wiki1')
|
|
assert_response(:success)
|
|
|
|
assert_equal ['animals', 'trees'], r.template_objects['categories']
|
|
# no category is specified in params
|
|
assert_nil r.template_objects['category']
|
|
assert_equal [@elephant, pages(:first_page), @home, pages(:my_way), pages(:no_wiki_word), @oak, pages(:smart_engine), pages(:that_way)], r.template_objects['pages_in_category'],
|
|
"Pages are not as expected: " +
|
|
r.template_objects['pages_in_category'].map {|p| p.name}.inspect
|
|
assert_equal 'the web', r.template_objects['set_name']
|
|
end
|
|
|
|
def test_recently_revised_with_specified_category
|
|
r = process('recently_revised', 'web' => 'wiki1', 'category' => 'animals')
|
|
assert_response(:success)
|
|
|
|
assert_equal ['animals', 'trees'], r.template_objects['categories']
|
|
# no category is specified in params
|
|
assert_equal 'animals', r.template_objects['category']
|
|
assert_equal [@elephant], r.template_objects['pages_in_category']
|
|
assert_equal "category 'animals'", r.template_objects['set_name']
|
|
end
|
|
|
|
|
|
def test_revision
|
|
r = process 'revision', 'web' => 'wiki1', 'id' => 'HomePage', 'rev' => '1'
|
|
|
|
assert_response(:success)
|
|
assert_equal @home, r.template_objects['page']
|
|
assert_equal @home.revisions[0], r.template_objects['revision']
|
|
end
|
|
|
|
|
|
def test_rollback
|
|
# rollback shows a form where a revision can be edited.
|
|
# its assigns the same as or revision
|
|
r = process 'rollback', 'web' => 'wiki1', 'id' => 'HomePage', 'rev' => '1'
|
|
|
|
assert_response(:success)
|
|
assert_equal @home, r.template_objects['page']
|
|
assert_equal @home.revisions[0], r.template_objects['revision']
|
|
end
|
|
|
|
def test_atom_with_content
|
|
r = process 'atom_with_content', 'web' => 'wiki1'
|
|
|
|
assert_response(:success)
|
|
pages = r.template_objects['pages_by_revision']
|
|
assert_equal [@elephant, @oak, pages(:no_wiki_word), pages(:that_way), pages(:smart_engine), pages(:my_way), pages(:first_page), @home], pages,
|
|
"Pages are not as expected: #{pages.map {|p| p.name}.inspect}"
|
|
assert !r.template_objects['hide_description']
|
|
end
|
|
|
|
def test_atom_with_content_when_blocked
|
|
@web.update_attributes(:password => 'aaa', :published => false)
|
|
@web = Web.find(@web.id)
|
|
|
|
r = process 'atom_with_content', 'web' => 'wiki1'
|
|
|
|
assert_equal 403, r.response_code
|
|
end
|
|
|
|
|
|
def test_atom_with_headlines
|
|
@title_with_spaces = @wiki.write_page('wiki1', 'Title With Spaces',
|
|
'About spaces', 1.hour.ago, Author.new('TreeHugger', '127.0.0.2'), test_renderer)
|
|
|
|
@request.host = 'localhost'
|
|
@request.port = 8080
|
|
|
|
r = process 'atom_with_headlines', 'web' => 'wiki1'
|
|
|
|
assert_response(:success)
|
|
pages = r.template_objects['pages_by_revision']
|
|
assert_equal [@elephant, @title_with_spaces, @oak, pages(:no_wiki_word), pages(:that_way), pages(:smart_engine), pages(:my_way), pages(:first_page), @home], pages, "Pages are not as expected: #{pages.map {|p| p.name}.inspect}"
|
|
assert r.template_objects['hide_description']
|
|
|
|
xml = REXML::Document.new(r.body)
|
|
|
|
expected_page_links =
|
|
['http://localhost:8080/wiki1/show/Elephant',
|
|
'http://localhost:8080/wiki1/show/Title+With+Spaces',
|
|
'http://localhost:8080/wiki1/show/Oak',
|
|
'http://localhost:8080/wiki1/show/NoWikiWord',
|
|
'http://localhost:8080/wiki1/show/ThatWay',
|
|
'http://localhost:8080/wiki1/show/SmartEngine',
|
|
'http://localhost:8080/wiki1/show/MyWay',
|
|
'http://localhost:8080/wiki1/show/FirstPage',
|
|
'http://localhost:8080/wiki1/show/HomePage',
|
|
]
|
|
|
|
assert_tag :tag => 'link',
|
|
:parent => {:tag => 'feed'},
|
|
:attributes => { :rel => 'alternate',
|
|
:href => 'http://localhost:8080/wiki1/show/HomePage'}
|
|
expected_page_links.each do |link|
|
|
assert_tag :tag => 'link',
|
|
:parent => {:tag => 'entry'},
|
|
:attributes => {:href => link }
|
|
end
|
|
end
|
|
|
|
def test_atom_switch_links_to_published
|
|
@web.update_attributes(:password => 'aaa', :published => true)
|
|
@web = Web.find(@web.id)
|
|
|
|
@request.host = 'foo.bar.info'
|
|
@request.port = 80
|
|
|
|
r = process 'atom_with_headlines', 'web' => 'wiki1'
|
|
|
|
assert_response(:success)
|
|
xml = REXML::Document.new(r.body)
|
|
|
|
expected_page_links =
|
|
['http://foo.bar.info/wiki1/published/Elephant',
|
|
'http://foo.bar.info/wiki1/published/Oak',
|
|
'http://foo.bar.info/wiki1/published/NoWikiWord',
|
|
'http://foo.bar.info/wiki1/published/ThatWay',
|
|
'http://foo.bar.info/wiki1/published/SmartEngine',
|
|
'http://foo.bar.info/wiki1/published/MyWay',
|
|
'http://foo.bar.info/wiki1/published/FirstPage',
|
|
'http://foo.bar.info/wiki1/published/HomePage']
|
|
|
|
assert_tag :tag => 'link',
|
|
:parent =>{:tag =>'feed'},
|
|
:attributes => {:rel => 'alternate',
|
|
:href => 'http://foo.bar.info/wiki1/published/HomePage'}
|
|
expected_page_links.each do |link|
|
|
assert_tag :tag => 'link',
|
|
:parent => {:tag => 'entry'},
|
|
:attributes => {:href => link}
|
|
end
|
|
end
|
|
|
|
# def test_atom_with_params
|
|
# setup_wiki_with_30_pages
|
|
#
|
|
# r = process 'atom_with_headlines', 'web' => 'wiki1'
|
|
# assert_response(:success)
|
|
# pages = r.template_objects['pages_by_revision']
|
|
# assert_equal 15, pages.size, 15
|
|
#
|
|
# r = process 'atom_with_headlines', 'web' => 'wiki1', 'limit' => '5'
|
|
# assert_response(:success)
|
|
# pages = r.template_objects['pages_by_revision']
|
|
# assert_equal 5, pages.size
|
|
#
|
|
# r = process 'atom_with_headlines', 'web' => 'wiki1', 'limit' => '25'
|
|
# assert_response(:success)
|
|
# pages = r.template_objects['pages_by_revision']
|
|
# assert_equal 25, pages.size
|
|
#
|
|
# r = process 'atom_with_headlines', 'web' => 'wiki1', 'limit' => 'all'
|
|
# assert_response(:success)
|
|
# pages = r.template_objects['pages_by_revision']
|
|
# assert_equal 38, pages.size
|
|
#
|
|
# r = process 'atom_with_headlines', 'web' => 'wiki1', 'start' => '1976-10-16'
|
|
# assert_response(:success)
|
|
# pages = r.template_objects['pages_by_revision']
|
|
# assert_equal 23, pages.size
|
|
#
|
|
# r = process 'atom_with_headlines', 'web' => 'wiki1', 'end' => '1976-10-16'
|
|
# assert_response(:success)
|
|
# pages = r.template_objects['pages_by_revision']
|
|
# assert_equal 15, pages.size
|
|
#
|
|
# r = process 'atom_with_headlines', 'web' => 'wiki1', 'start' => '1976-10-01', 'end' => '1976-10-06'
|
|
# assert_response(:success)
|
|
# pages = r.template_objects['pages_by_revision']
|
|
# assert_equal 5, pages.size
|
|
# end
|
|
|
|
def test_atom_title_with_ampersand
|
|
# was ticket:143
|
|
# Since we're declaring <title> to be of type="html", the content is unescaped once before interpreting.
|
|
# Evidently, the desired behaviour is that the final result be HTML-encoded. Hence the double-encoding here.
|
|
@wiki.write_page('wiki1', 'Title&With&Ampersands',
|
|
'About spaces', 1.hour.ago, Author.new('NitPicker', '127.0.0.3'), test_renderer)
|
|
|
|
r = process 'atom_with_headlines', 'web' => 'wiki1'
|
|
|
|
assert r.body.include?('<title type="html">Home Page</title>')
|
|
assert r.body.include?('<title type="html">Title&amp;With&amp;Ampersands</title>')
|
|
end
|
|
|
|
def test_atom_timestamp
|
|
new_page = @wiki.write_page('wiki1', 'PageCreatedAtTheBeginningOfCtime',
|
|
'Created on 1 Jan 1970 at 0:00:00 Z', Time.at(0), Author.new('NitPicker', '127.0.0.3'),
|
|
test_renderer)
|
|
|
|
r = process 'atom_with_headlines', 'web' => 'wiki1'
|
|
assert_tag :tag =>'published',
|
|
:parent => {:tag => 'entry'},
|
|
:content => '2004-04-04T21:50:00Z'
|
|
end
|
|
|
|
def test_save
|
|
r = process 'save', 'web' => 'wiki1', 'id' => 'NewPage', 'content' => 'Contents of a new page',
|
|
'author' => 'AuthorOfNewPage'
|
|
|
|
assert_redirected_to :web => 'wiki1', :action => 'show', :id => 'NewPage'
|
|
assert_equal ['AuthorOfNewPage'], r.cookies['author'].value
|
|
assert_equal Time.utc(2030), r.cookies['author'].expires
|
|
new_page = @wiki.read_page('wiki1', 'NewPage')
|
|
assert_equal 'Contents of a new page', new_page.content
|
|
assert_equal 'AuthorOfNewPage', new_page.author
|
|
end
|
|
|
|
def test_save_not_utf8
|
|
r = process 'save', 'web' => 'wiki1', 'id' => 'NewPage', 'content' => "Contents of a new page\r\n\000",
|
|
'author' => 'AuthorOfNewPage'
|
|
|
|
assert_redirected_to :web => 'wiki1', :action => 'new', :id => 'NewPage'
|
|
assert_equal ['AuthorOfNewPage'], r.cookies['author'].value
|
|
assert_equal Time.utc(2030), r.cookies['author'].expires
|
|
end
|
|
|
|
def test_save_not_utf8_ncr
|
|
r = process 'save', 'web' => 'wiki1', 'id' => 'NewPage', 'content' => "Contents of a new page\r\n",
|
|
'author' => 'AuthorOfNewPage'
|
|
|
|
assert_redirected_to :web => 'wiki1', :action => 'new', :id => 'NewPage'
|
|
assert_equal ['AuthorOfNewPage'], r.cookies['author'].value
|
|
assert_equal Time.utc(2030), r.cookies['author'].expires
|
|
end
|
|
|
|
def test_save_not_utf8_dec_ncr
|
|
r = process 'save', 'web' => 'wiki1', 'id' => 'NewPage', 'content' => "Contents of a new page\r\n",
|
|
'author' => 'AuthorOfNewPage'
|
|
|
|
assert_redirected_to :web => 'wiki1', :action => 'new', :id => 'NewPage'
|
|
assert_equal ['AuthorOfNewPage'], r.cookies['author'].value
|
|
assert_equal Time.utc(2030), r.cookies['author'].expires
|
|
end
|
|
|
|
def test_save_new_revision_of_existing_page
|
|
@home.lock(Time.now, 'Batman')
|
|
current_revisions = @home.revisions.size
|
|
|
|
r = process 'save', 'web' => 'wiki1', 'id' => 'HomePage', 'content' => 'Revised HomePage',
|
|
'author' => 'Batman'
|
|
|
|
assert_redirected_to :web => 'wiki1', :action => 'show', :id => 'HomePage'
|
|
assert_equal ['Batman'], r.cookies['author'].value
|
|
home_page = @wiki.read_page('wiki1', 'HomePage')
|
|
assert_equal current_revisions+1, home_page.revisions.size
|
|
assert_equal 'Revised HomePage', home_page.content
|
|
assert_equal 'Batman', home_page.author
|
|
assert !home_page.locked?(Time.now)
|
|
end
|
|
|
|
def test_save_new_revision_identical_to_last
|
|
revisions_before = @home.revisions.size
|
|
@home.lock(Time.now, 'AnAuthor')
|
|
|
|
r = process 'save', {'web' => 'wiki1', 'id' => 'HomePage',
|
|
'content' => @home.revisions.last.content.dup,
|
|
'author' => 'SomeOtherAuthor'}, {:return_to => '/wiki1/show/HomePage'}
|
|
|
|
assert_redirected_to :action => 'edit', :web => 'wiki1', :id => 'HomePage'
|
|
# assert(@response.has_key(:error))
|
|
assert r.flash[:error].kind_of?(Instiki::ValidationError)
|
|
|
|
revisions_after = @home.revisions.size
|
|
assert_equal revisions_before, revisions_after
|
|
@home = Page.find(@home.id)
|
|
assert !@home.locked?(Time.now), 'HomePage should be unlocked if an edit was unsuccessful'
|
|
end
|
|
|
|
def test_save_blank_author
|
|
r = process 'save', 'web' => 'wiki1', 'id' => 'NewPage', 'content' => 'Contents of a new page',
|
|
'author' => ''
|
|
new_page = @wiki.read_page('wiki1', 'NewPage')
|
|
assert_equal 'AnonymousCoward', new_page.author
|
|
|
|
r = process 'save', 'web' => 'wiki1', 'id' => 'AnotherPage', 'content' => 'Contents of a new page',
|
|
'author' => ' '
|
|
|
|
another_page = @wiki.read_page('wiki1', 'AnotherPage')
|
|
assert_equal 'AnonymousCoward', another_page.author
|
|
end
|
|
|
|
|
|
def test_search
|
|
r = process 'search', 'web' => 'wiki1', 'query' => '\s[A-Z]ak'
|
|
|
|
assert_redirected_to :action => 'show', :id => 'Oak'
|
|
end
|
|
|
|
def test_search_multiple_results
|
|
r = process 'search', 'web' => 'wiki1', 'query' => 'All about'
|
|
|
|
assert_response(:success)
|
|
assert_equal 'All about', r.template_objects['query']
|
|
assert_equal [@elephant, @oak], r.template_objects['results']
|
|
assert_equal [], r.template_objects['title_results']
|
|
end
|
|
|
|
def test_search_by_content_and_title
|
|
r = process 'search', 'web' => 'wiki1', 'query' => '(Oak|Elephant)'
|
|
|
|
assert_response(:success)
|
|
assert_equal '(Oak|Elephant)', r.template_objects['query']
|
|
assert_equal [@elephant, @oak], r.template_objects['results']
|
|
assert_equal [@elephant, @oak], r.template_objects['title_results']
|
|
end
|
|
|
|
def test_search_zero_results
|
|
r = process 'search', 'web' => 'wiki1', 'query' => 'non-existant text'
|
|
|
|
assert_response(:success)
|
|
assert_equal [], r.template_objects['results']
|
|
assert_equal [], r.template_objects['title_results']
|
|
end
|
|
|
|
def test_search_null_in_query
|
|
r = process 'search', 'web' => 'wiki1', 'query' => "\x00"
|
|
|
|
assert_response(400)
|
|
assert_match /Your query string was not valid utf-8/, r.body
|
|
end
|
|
|
|
def test_search_FFFF_in_query
|
|
r = process 'search', 'web' => 'wiki1', 'query' => "\xEF\xBF\xBF"
|
|
|
|
assert_response(400)
|
|
assert_match /Your query string was not valid utf-8/, r.body
|
|
end
|
|
|
|
def test_search_FFFD_in_query
|
|
r = process 'search', 'web' => 'wiki1', 'query' => "\xEF\xBF\xBD"
|
|
|
|
assert_response(:success)
|
|
assert_equal [], r.template_objects['results']
|
|
assert_equal [], r.template_objects['title_results']
|
|
end
|
|
|
|
def test_show_page
|
|
r = process 'show', 'id' => 'Oak', 'web' => 'wiki1'
|
|
assert_response :success
|
|
assert_tag :content => /All about oak/
|
|
end
|
|
|
|
def test_show_page_with_multiple_revisions
|
|
@wiki.write_page('wiki1', 'HomePage', 'Second revision of the HomePage end', Time.now,
|
|
Author.new('AnotherAuthor', '127.0.0.2'), test_renderer)
|
|
|
|
r = process('show', 'id' => 'HomePage', 'web' => 'wiki1')
|
|
|
|
assert_response :success
|
|
assert_match /Second revision of the <a.*HomePage.*<\/a> end/, r.body
|
|
end
|
|
|
|
def test_show_page_nonexistant_page
|
|
process('show', 'id' => 'UnknownPage', 'web' => 'wiki1')
|
|
assert_redirected_to :web => 'wiki1', :action => 'new', :id => 'UnknownPage'
|
|
end
|
|
|
|
def test_show_no_page
|
|
r = process('show', 'id' => '', 'web' => 'wiki1')
|
|
assert_response :missing
|
|
|
|
r = process('show', 'web' => 'wiki1')
|
|
assert_response :missing
|
|
end
|
|
|
|
def test_tex
|
|
r = process('tex', 'web' => 'wiki1', 'id' => 'HomePage')
|
|
assert_response(:success)
|
|
|
|
assert_equal %q!\documentclass[12pt,titlepage]{article}
|
|
|
|
\usepackage{amsmath}
|
|
\usepackage{amsfonts}
|
|
\usepackage{amssymb}
|
|
\usepackage{graphicx}
|
|
\usepackage{color}
|
|
\usepackage{ucs}
|
|
\usepackage[utf8x]{inputenc}
|
|
\usepackage{hyperref}
|
|
|
|
%----Macros----------
|
|
%
|
|
% Unresolved issues:
|
|
%
|
|
% \righttoleftarrow
|
|
% \lefttorightarrow
|
|
%
|
|
% \color{} with HTML colorspec
|
|
% \bgcolor
|
|
% \array
|
|
|
|
% Of the standard HTML named colors, white, black, red, green, blue and yellow
|
|
% are predefined in the color package. Here are the rest.
|
|
\definecolor{aqua}{rgb}{0, 1.0, 1.0}
|
|
\definecolor{fuschia}{rgb}{1.0, 0, 1.0}
|
|
\definecolor{gray}{rgb}{0.502, 0.502, 0.502}
|
|
\definecolor{lime}{rgb}{0, 1.0, 0}
|
|
\definecolor{maroon}{rgb}{0.502, 0, 0}
|
|
\definecolor{navy}{rgb}{0, 0, 0.502}
|
|
\definecolor{olive}{rgb}{0.502, 0.502, 0}
|
|
\definecolor{purple}{rgb}{0.502, 0, 0.502}
|
|
\definecolor{silver}{rgb}{0.753, 0.753, 0.753}
|
|
\definecolor{teal}{rgb}{0, 0.502, 0.502}
|
|
|
|
% Because of conflicts, \space and \mathop are converted to
|
|
% \itexspace and \operatorname during preprocessing.
|
|
|
|
% itex: \space{ht}{dp}{wd}
|
|
%
|
|
% Height and baseline depth measurements are in units of tenths of an ex while
|
|
% the width is measured in tenths of an em.
|
|
\makeatletter
|
|
\newdimen\itex@wd%
|
|
\newdimen\itex@dp%
|
|
\newdimen\itex@thd%
|
|
\def\itexspace#1#2#3{\itex@wd=#3em%
|
|
\itex@wd=0.1\itex@wd%
|
|
\itex@dp=#2ex%
|
|
\itex@dp=0.1\itex@dp%
|
|
\itex@thd=#1ex%
|
|
\itex@thd=0.1\itex@thd%
|
|
\advance\itex@thd\the\itex@dp%
|
|
\makebox[\the\itex@wd]{\rule[-\the\itex@dp]{0cm}{\the\itex@thd}}}
|
|
\makeatother
|
|
|
|
% \tensor and \multiscript
|
|
\makeatletter
|
|
\newif\if@sup
|
|
\newtoks\@sups
|
|
\def\append@sup#1{\edef\act{\noexpand\@sups={\the\@sups #1}}\act}%
|
|
\def\reset@sup{\@supfalse\@sups={}}%
|
|
\def\mk@scripts#1#2{\if #2/ \if@sup ^{\the\@sups}\fi \else%
|
|
\ifx #1_ \if@sup ^{\the\@sups}\reset@sup \fi {}_{#2}%
|
|
\else \append@sup#2 \@suptrue \fi%
|
|
\expandafter\mk@scripts\fi}
|
|
\def\tensor#1#2{\reset@sup#1\mk@scripts#2_/}
|
|
\def\multiscripts#1#2#3{\reset@sup{}\mk@scripts#1_/#2%
|
|
\reset@sup\mk@scripts#3_/}
|
|
\makeatother
|
|
|
|
% \slash
|
|
\makeatletter
|
|
\newbox\slashbox \setbox\slashbox=\hbox{$/$}
|
|
\def\itex@pslash#1{\setbox\@tempboxa=\hbox{$#1$}
|
|
\@tempdima=0.5\wd\slashbox \advance\@tempdima 0.5\wd\@tempboxa
|
|
\copy\slashbox \kern-\@tempdima \box\@tempboxa}
|
|
\def\slash{\protect\itex@pslash}
|
|
\makeatother
|
|
|
|
% Renames \sqrt as \oldsqrt and redefine root to result in \sqrt[#1]{#2}
|
|
\let\oldroot\root
|
|
\def\root#1#2{\oldroot #1 \of{#2}}
|
|
|
|
% Manually declare the txfonts symbolsC font
|
|
\DeclareSymbolFont{symbolsC}{U}{txsyc}{m}{n}
|
|
\SetSymbolFont{symbolsC}{bold}{U}{txsyc}{bx}{n}
|
|
\DeclareFontSubstitution{U}{txsyc}{m}{n}
|
|
|
|
% Declare specific arrows from txfonts without loading the full package
|
|
\makeatletter
|
|
\def\re@DeclareMathSymbol#1#2#3#4{%
|
|
\let#1=\undefined
|
|
\DeclareMathSymbol{#1}{#2}{#3}{#4}}
|
|
\re@DeclareMathSymbol{\neArrow}{\mathrel}{symbolsC}{116}
|
|
\re@DeclareMathSymbol{\neArr}{\mathrel}{symbolsC}{116}
|
|
\re@DeclareMathSymbol{\seArrow}{\mathrel}{symbolsC}{117}
|
|
\re@DeclareMathSymbol{\seArr}{\mathrel}{symbolsC}{117}
|
|
\re@DeclareMathSymbol{\nwArrow}{\mathrel}{symbolsC}{118}
|
|
\re@DeclareMathSymbol{\nwArr}{\mathrel}{symbolsC}{118}
|
|
\re@DeclareMathSymbol{\swArrow}{\mathrel}{symbolsC}{119}
|
|
\re@DeclareMathSymbol{\swArr}{\mathrel}{symbolsC}{119}
|
|
\re@DeclareMathSymbol{\nequiv}{\mathrel}{symbolsC}{46}
|
|
\re@DeclareMathSymbol{\Perp}{\mathrel}{symbolsC}{121}
|
|
\re@DeclareMathSymbol{\Vbar}{\mathrel}{symbolsC}{121}
|
|
\makeatother
|
|
|
|
% Widecheck
|
|
\makeatletter
|
|
\DeclareRobustCommand\widecheck[1]{{\mathpalette\@widecheck{#1}}}
|
|
\def\@widecheck#1#2{%
|
|
\setbox\z@\hbox{\m@th$#1#2$}%
|
|
\setbox\tw@\hbox{\m@th$#1%
|
|
\widehat{%
|
|
\vrule\@width\z@\@height\ht\z@
|
|
\vrule\@height\z@\@width\wd\z@}$}%
|
|
\dp\tw@-\ht\z@
|
|
\@tempdima\ht\z@ \advance\@tempdima2\ht\tw@ \divide\@tempdima\thr@@
|
|
\setbox\tw@\hbox{%
|
|
\raise\@tempdima\hbox{\scalebox{1}[-1]{\lower\@tempdima\box
|
|
\tw@}}}%
|
|
{\ooalign{\box\tw@ \cr \box\z@}}}
|
|
\makeatother
|
|
|
|
% udots (taken from yhmath)
|
|
\makeatletter
|
|
\def\udots{\mathinner{\mkern2mu\raise\p@\hbox{.}
|
|
\mkern2mu\raise4\p@\hbox{.}\mkern1mu
|
|
\raise7\p@\vbox{\kern7\p@\hbox{.}}\mkern1mu}}
|
|
\makeatother
|
|
|
|
%% Renaming existing commands
|
|
\newcommand{\underoverset}[3]{\underset{#1}{\overset{#2}{#3}}}
|
|
\newcommand{\widevec}{\overrightarrow}
|
|
\newcommand{\darr}{\downarrow}
|
|
\newcommand{\nearr}{\nearrow}
|
|
\newcommand{\nwarr}{\nwarrow}
|
|
\newcommand{\searr}{\searrow}
|
|
\newcommand{\swarr}{\swarrow}
|
|
\newcommand{\curvearrowbotright}{\curvearrowright}
|
|
\newcommand{\uparr}{\uparrow}
|
|
\newcommand{\downuparrow}{\updownarrow}
|
|
\newcommand{\duparr}{\updownarrow}
|
|
\newcommand{\updarr}{\updownarrow}
|
|
\newcommand{\gt}{>}
|
|
\newcommand{\lt}{<}
|
|
\newcommand{\map}{\mapsto}
|
|
\newcommand{\embedsin}{\hookrightarrow}
|
|
\newcommand{\Alpha}{A}
|
|
\newcommand{\Beta}{B}
|
|
\newcommand{\Zeta}{Z}
|
|
\newcommand{\Eta}{H}
|
|
\newcommand{\Iota}{I}
|
|
\newcommand{\Kappa}{K}
|
|
\newcommand{\Mu}{M}
|
|
\newcommand{\Nu}{N}
|
|
\newcommand{\Rho}{P}
|
|
\newcommand{\Tau}{T}
|
|
\newcommand{\Upsi}{\Upsilon}
|
|
\newcommand{\omicron}{o}
|
|
\newcommand{\lang}{\langle}
|
|
\newcommand{\rang}{\rangle}
|
|
\newcommand{\Union}{\bigcup}
|
|
\newcommand{\Intersection}{\bigcap}
|
|
\newcommand{\Oplus}{\bigoplus}
|
|
\newcommand{\Otimes}{\bigotimes}
|
|
\newcommand{\Wedge}{\bigwedge}
|
|
\newcommand{\Vee}{\bigvee}
|
|
\newcommand{\coproduct}{\coprod}
|
|
\newcommand{\product}{\prod}
|
|
\newcommand{\closure}{\overline}
|
|
\newcommand{\integral}{\int}
|
|
\newcommand{\doubleintegral}{\iint}
|
|
\newcommand{\tripleintegral}{\iiint}
|
|
\newcommand{\quadrupleintegral}{\iiiint}
|
|
\newcommand{\conint}{\oint}
|
|
\newcommand{\contourintegral}{\oint}
|
|
\newcommand{\qed}{\blacksquare}
|
|
\newcommand{\infinity}{\infty}
|
|
\renewcommand{\empty}{\emptyset}
|
|
\newcommand{\bottom}{\bot}
|
|
\newcommand{\minusb}{\boxminus}
|
|
\newcommand{\plusb}{\boxplus}
|
|
\newcommand{\timesb}{\boxtimes}
|
|
\newcommand{\intersection}{\cap}
|
|
\newcommand{\union}{\cup}
|
|
\newcommand{\Del}{\nabla}
|
|
\newcommand{\odash}{\circleddash}
|
|
\newcommand{\negspace}{\\\!}
|
|
\newcommand{\widebar}{\overline}
|
|
\newcommand{\textsize}{\normalsize}
|
|
\renewcommand{\scriptsize}{\scriptstyle}
|
|
\newcommand{\scriptscriptsize}{\scriptscriptstyle}
|
|
\newcommand{\mathfr}{\mathfrak}
|
|
\newcommand{\statusline}[2]{#2}
|
|
\newcommand{\toggle}[2]{#1}
|
|
|
|
%-------------------------------------------------------------------
|
|
|
|
\begin{document}
|
|
|
|
%-------------------------------------------------------------------
|
|
|
|
\section*{HomePage}
|
|
|
|
HisWay would be MyWay $\sin(x) \includegraphics[width=3em]{foo}$ in kinda ThatWay in HisWay though MyWay $\backslash$OverThere --{} see SmartEngine in that SmartEngineGUI
|
|
|
|
|
|
|
|
\end{document}
|
|
!, r.body
|
|
end
|
|
|
|
|
|
def test_web_list
|
|
another_wiki = @wiki.create_web('Another Wiki', 'another_wiki')
|
|
|
|
r = process('web_list')
|
|
|
|
assert_response(:success)
|
|
assert_equal [another_wiki, webs(:instiki), @web], r.template_objects['webs']
|
|
end
|
|
|
|
end
|