Rails 2.3.5

Upgrade to Rails 2.3.5.
Also work around this bug:
 https://rails.lighthouseapp.com/projects/8994/tickets/3524
created by the aforementioned
Rails release.
This commit is contained in:
Jacques Distler 2009-11-30 19:38:34 -06:00
parent a6429f8c22
commit e3832c6f79
187 changed files with 2316 additions and 891 deletions

View file

@ -212,11 +212,11 @@ class AdminControllerTest < ActionController::TestCase
def test_remove_orphaned_pages
@wiki.system.update_attribute(:password, 'pswd')
page_order = [@home, pages(:my_way), @oak, pages(:smart_engine), pages(:that_way), @liquor]
test_renderer(@web.page('liquor').revisions.last).display_content(true)
x_test_renderer(@web.page('liquor').revisions.last).display_content(true)
orphan_page_linking_to_oak_and_redirecting_to_liquor = @wiki.write_page('wiki1', 'Pine',
"Refers to [[Oak]] and to [[booze]].\n" +
"category: trees",
Time.now, Author.new('TreeHugger', '127.0.0.2'), test_renderer)
Time.now, Author.new('TreeHugger', '127.0.0.2'), x_test_renderer)
r = process('remove_orphaned_pages', 'web' => 'wiki1', 'system_password_orphaned' => 'pswd')
@ -249,7 +249,7 @@ class AdminControllerTest < ActionController::TestCase
orphan_page_linking_to_oak = @wiki.write_page('wiki1', 'Pine',
"Refers to [[Oak]].\n" +
"category: trees",
Time.now, Author.new('TreeHugger', '127.0.0.2'), test_renderer)
Time.now, Author.new('TreeHugger', '127.0.0.2'), x_test_renderer)
r = process('remove_orphaned_pages_in_category', 'web' => 'wiki1', 'category' => 'trees','system_password_orphaned_in_category' => 'pswd')

View file

@ -55,7 +55,7 @@ class WikiControllerTest < ActionController::TestCase
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)
Time.now, Author.new('BreakingTheOrder', '127.0.0.2'), x_test_renderer)
r = process('authors', 'web' => 'wiki1')
@ -106,7 +106,7 @@ class WikiControllerTest < ActionController::TestCase
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)
x_test_renderer)
r = process 'edit', 'web' => 'wiki1', 'id' => 'With : Special /> symbols'
assert_response(:success)
@ -118,7 +118,7 @@ class WikiControllerTest < ActionController::TestCase
def test_export_xhtml
@request.accept = 'application/xhtml+xml'
# rollback homepage to a version that is easier to match
@home.rollback(0, Time.now, 'Rick', test_renderer)
@home.rollback(0, Time.now, 'Rick', x_test_renderer)
r = process 'export_html', 'web' => 'wiki1'
assert_response(:success, bypass_body_parsing = true)
@ -149,7 +149,7 @@ class WikiControllerTest < ActionController::TestCase
def test_export_html
@request.accept = 'tex/html'
# rollback homepage to a version that is easier to match
@home.rollback(0, Time.now, 'Rick', test_renderer)
@home.rollback(0, Time.now, 'Rick', x_test_renderer)
r = process 'export_html', 'web' => 'wiki1'
assert_response(:success, bypass_body_parsing = true)
@ -423,7 +423,7 @@ class WikiControllerTest < ActionController::TestCase
page2 = @wiki.write_page('wiki1', 'Page2',
"Page2 contents.\n" +
"category: categorized",
Time.now, Author.new('AnotherAuthor', '127.0.0.2'), test_renderer)
Time.now, Author.new('AnotherAuthor', '127.0.0.2'), x_test_renderer)
r = process('recently_revised', 'web' => 'wiki1')
assert_response(:success)
@ -508,7 +508,7 @@ class WikiControllerTest < ActionController::TestCase
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)
'About spaces', 1.hour.ago, Author.new('TreeHugger', '127.0.0.2'), x_test_renderer)
@request.host = 'localhost'
@request.port = 8080
@ -622,7 +622,7 @@ class WikiControllerTest < ActionController::TestCase
# 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)
'About spaces', 1.hour.ago, Author.new('NitPicker', '127.0.0.3'), x_test_renderer)
r = process 'atom_with_headlines', 'web' => 'wiki1'
@ -633,7 +633,7 @@ class WikiControllerTest < ActionController::TestCase
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)
x_test_renderer)
r = process 'atom_with_headlines', 'web' => 'wiki1'
assert_tag :tag =>'published',
@ -921,7 +921,7 @@ class WikiControllerTest < ActionController::TestCase
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)
Author.new('AnotherAuthor', '127.0.0.2'), x_test_renderer)
r = process('show', 'id' => 'HomePage', 'web' => 'wiki1')
@ -931,7 +931,7 @@ class WikiControllerTest < ActionController::TestCase
def test_recursive_include
@wiki.write_page('wiki1', 'HomePage', 'Self-include: [[!include HomePage]]', Time.now,
Author.new('AnotherAuthor', '127.0.0.2'), test_renderer)
Author.new('AnotherAuthor', '127.0.0.2'), x_test_renderer)
r = process('show', 'id' => 'HomePage', 'web' => 'wiki1')
@ -941,9 +941,9 @@ class WikiControllerTest < ActionController::TestCase
def test_recursive_include_II
@wiki.write_page('wiki1', 'Foo', "extra fun [[!include HomePage]]", Time.now,
Author.new('AnotherAuthor', '127.0.0.2'), test_renderer)
Author.new('AnotherAuthor', '127.0.0.2'), x_test_renderer)
@wiki.write_page('wiki1', 'HomePage', "Recursive-include:\n\n[[!include Foo]]", Time.now,
Author.new('AnotherAuthor', '127.0.0.2'), test_renderer)
Author.new('AnotherAuthor', '127.0.0.2'), x_test_renderer)
r = process('show', 'id' => 'HomePage', 'web' => 'wiki1')
@ -953,11 +953,11 @@ class WikiControllerTest < ActionController::TestCase
def test_recursive_include_III
@wiki.write_page('wiki1', 'Bar', "extra fun\n\n[[!include HomePage]]", Time.now,
Author.new('AnotherAuthor', '127.0.0.2'), test_renderer)
Author.new('AnotherAuthor', '127.0.0.2'), x_test_renderer)
@wiki.write_page('wiki1', 'Foo', "[[!include Bar]]\n\n[[!include Bar]]", Time.now,
Author.new('AnotherAuthor', '127.0.0.2'), test_renderer)
Author.new('AnotherAuthor', '127.0.0.2'), x_test_renderer)
@wiki.write_page('wiki1', 'HomePage', "Recursive-include:\n\n[[!include Foo]]", Time.now,
Author.new('AnotherAuthor', '127.0.0.2'), test_renderer)
Author.new('AnotherAuthor', '127.0.0.2'), x_test_renderer)
r = process('show', 'id' => 'HomePage', 'web' => 'wiki1')
@ -967,11 +967,11 @@ class WikiControllerTest < ActionController::TestCase
def test_nonrecursive_include
@wiki.write_page('wiki1', 'Bar', "extra fun\n\n[[HomePage]]", Time.now,
Author.new('AnotherAuthor', '127.0.0.2'), test_renderer)
Author.new('AnotherAuthor', '127.0.0.2'), x_test_renderer)
@wiki.write_page('wiki1', 'Foo', "[[!include Bar]]\n\n[[!include Bar]]", Time.now,
Author.new('AnotherAuthor', '127.0.0.2'), test_renderer)
Author.new('AnotherAuthor', '127.0.0.2'), x_test_renderer)
@wiki.write_page('wiki1', 'HomePage', "Nonrecursive-include:\n\n[[!include Foo]]", Time.now,
Author.new('AnotherAuthor', '127.0.0.2'), test_renderer)
Author.new('AnotherAuthor', '127.0.0.2'), x_test_renderer)
r = process('show', 'id' => 'HomePage', 'web' => 'wiki1')
@ -1258,7 +1258,7 @@ HisWay would be MyWay $\sin(x) \includegraphics[width=3em]{foo}$ in kinda ThatWa
def test_tex_with_blackboard_digits
@wiki.write_page('wiki1', 'Page2',
"Page2 contents $\\mathbb{01234}$.\n",
Time.now, Author.new('AnotherAuthor', '127.0.0.2'), test_renderer)
Time.now, Author.new('AnotherAuthor', '127.0.0.2'), x_test_renderer)
r = process('tex', 'web' => 'wiki1', 'id' => 'Page2')
assert_response(:success)

View file

@ -43,13 +43,13 @@ class Test::Unit::TestCase
(1..30).each do |i|
@wiki.write_page('wiki1', "page#{i}", "Test page #{i}\ncategory: test",
Time.local(1976, 10, i, 12, 00, 00), Author.new('Dema', '127.0.0.2'),
test_renderer)
x_test_renderer)
end
end
@web = Web.find(@web.id)
end
def test_renderer(revision = nil)
def x_test_renderer(revision = nil)
PageRenderer.setup_url_generator(StubUrlGenerator.new)
PageRenderer.new(revision)
end

View file

@ -15,14 +15,14 @@ class PageRendererTest < ActiveSupport::TestCase
def test_wiki_word_linking
@web.add_page('SecondPage', 'Yo, yo. Have you EverBeenHated',
Time.now, 'DavidHeinemeierHansson', test_renderer)
Time.now, 'DavidHeinemeierHansson', x_test_renderer)
assert_equal("<p>Yo, yo. Have you <span class='newWikiWord'>Ever Been Hated" +
"<a href='../show/EverBeenHated'>?</a></span></p>",
rendered_content(@web.page("SecondPage")))
@web.add_page('EverBeenHated', 'Yo, yo. Have you EverBeenHated', Time.now,
'DavidHeinemeierHansson', test_renderer)
'DavidHeinemeierHansson', x_test_renderer)
assert_equal("<p>Yo, yo. Have you <a class='existingWikiWord' " +
"href='../show/EverBeenHated'>Ever Been Hated</a></p>",
rendered_content(@web.page("SecondPage")))
@ -30,18 +30,18 @@ class PageRendererTest < ActiveSupport::TestCase
def test_wiki_words
assert_equal %w( HisWay MyWay SmartEngine SmartEngineGUI ThatWay ),
test_renderer(@revision).wiki_words.sort
x_test_renderer(@revision).wiki_words.sort
@wiki.write_page('wiki1', 'NoWikiWord', 'hey you!', Time.now, 'Me', test_renderer)
assert_equal [], test_renderer(@wiki.read_page('wiki1', 'NoWikiWord').revisions.last).wiki_words
@wiki.write_page('wiki1', 'NoWikiWord', 'hey you!', Time.now, 'Me', x_test_renderer)
assert_equal [], x_test_renderer(@wiki.read_page('wiki1', 'NoWikiWord').revisions.last).wiki_words
end
def test_existing_pages
assert_equal %w( MyWay SmartEngine ThatWay ), test_renderer(@revision).existing_pages.sort
assert_equal %w( MyWay SmartEngine ThatWay ), x_test_renderer(@revision).existing_pages.sort
end
def test_unexisting_pages
assert_equal %w( HisWay SmartEngineGUI ), test_renderer(@revision).unexisting_pages.sort
assert_equal %w( HisWay SmartEngineGUI ), x_test_renderer(@revision).unexisting_pages.sort
end
def test_content_with_wiki_links
@ -56,7 +56,7 @@ class PageRendererTest < ActiveSupport::TestCase
"<a class='existingWikiWord' href='../show/SmartEngine'>Smart Engine</a> in that " +
"<span class='newWikiWord'>Smart Engine GUI" +
"<a href='../show/SmartEngineGUI'>?</a></span></p>",
test_renderer(@revision).display_content
x_test_renderer(@revision).display_content
end
def test_markdown
@ -349,7 +349,7 @@ END_THM
assert_equal "<tt>hello</tt> that <span class='newWikiWord'>Smart Engine GUI" +
"<a href='../show/SmartEngineGUI'>?</a></span>\n\n",
test_renderer(@revision).display_content
x_test_renderer(@revision).display_content
end
# def test_content_with_auto_links
@ -555,7 +555,7 @@ END_THM
%{<a class='existingWikiWord' href='MyWay.html'>My Way</a> OverThere \342\200\223 see } +
"<a class='existingWikiWord' href='SmartEngine.html'>Smart Engine</a> in that " +
"<span class='newWikiWord'>Smart Engine GUI</span></p>",
test_renderer(@revision).display_content_for_export
x_test_renderer(@revision).display_content_for_export
end
def test_double_replacing
@ -564,21 +564,21 @@ END_THM
"<a href='../show/VersionHistory'>?</a></span></p>\n\n<p>cry " +
"<span class='newWikiWord'>Version History<a href='../show/VersionHistory'>?</a>" +
'</span></p>',
test_renderer(@revision).display_content
x_test_renderer(@revision).display_content
@revision.content = "f\r\nVersionHistory\r\n\r\ncry VersionHistory"
assert_equal "<p>f <span class='newWikiWord'>Version History" +
"<a href='../show/VersionHistory'>?</a></span></p>\n\n<p>cry " +
"<span class='newWikiWord'>Version History<a href='../show/VersionHistory'>?</a>" +
"</span></p>",
test_renderer(@revision).display_content
x_test_renderer(@revision).display_content
end
def test_difficult_wiki_words
@revision.content = "[[It's just awesome GUI!]]"
assert_equal "<p><span class='newWikiWord'>It&#39;s just awesome GUI!" +
"<a href='../show/It%27s+just+awesome+GUI%21'>?</a></span></p>",
test_renderer(@revision).display_content
x_test_renderer(@revision).display_content
end
def test_revisions_diff
@ -589,7 +589,7 @@ END_THM
@page.reload
assert_equal "<p><span> What a<del class='diffmod'> blue</del><ins class='diffmod'> red" +
"</ins> and lovely morning<ins class='diffins'> today</ins></span></p>", test_renderer(@page.revisions.last).display_diff
"</ins> and lovely morning<ins class='diffins'> today</ins></span></p>", x_test_renderer(@page.revisions.last).display_diff
end
def test_nowiki_sanitization
@ -687,7 +687,7 @@ END_THM
def test_references_creation_links
new_page = @web.add_page('NewPage', 'HomePage NewPage',
Time.local(2004, 4, 4, 16, 50), 'AlexeyVerkhovsky', test_renderer)
Time.local(2004, 4, 4, 16, 50), 'AlexeyVerkhovsky', x_test_renderer)
references = new_page.wiki_references(true)
assert_equal 2, references.size
@ -699,7 +699,7 @@ END_THM
def test_references_creation_includes
new_page = @web.add_page('NewPage', '[[!include IncludedPage]]',
Time.local(2004, 4, 4, 16, 50), 'AlexeyVerkhovsky', test_renderer)
Time.local(2004, 4, 4, 16, 50), 'AlexeyVerkhovsky', x_test_renderer)
references = new_page.wiki_references(true)
assert_equal 1, references.size
@ -709,7 +709,7 @@ END_THM
def test_references_creation_categories
new_page = @web.add_page('NewPage', "Foo\ncategory: NewPageCategory",
Time.local(2004, 4, 4, 16, 50), 'AlexeyVerkhovsky', test_renderer)
Time.local(2004, 4, 4, 16, 50), 'AlexeyVerkhovsky', x_test_renderer)
references = new_page.wiki_references(true)
assert_equal 1, references.size
@ -719,7 +719,7 @@ END_THM
def test_references_creation_sanitized_categories
new_page = @web.add_page('NewPage', "Foo\ncategory: <script>alert('XSS');</script>",
Time.local(2004, 4, 4, 16, 50), 'AlexeyVerkhovsky', test_renderer)
Time.local(2004, 4, 4, 16, 50), 'AlexeyVerkhovsky', x_test_renderer)
references = new_page.wiki_references(true)
assert_equal 1, references.size
@ -728,49 +728,49 @@ END_THM
end
def test_rendering_included_page_under_different_modes
included = @web.add_page('Included', 'link to HomePage', Time.now, 'AnAuthor', test_renderer)
main = @web.add_page('Main', '[[!include Included]]', Time.now, 'AnAuthor', test_renderer)
included = @web.add_page('Included', 'link to HomePage', Time.now, 'AnAuthor', x_test_renderer)
main = @web.add_page('Main', '[[!include Included]]', Time.now, 'AnAuthor', x_test_renderer)
assert_equal "<p>link to <a class='existingWikiWord' href='../show/HomePage'>Home Page</a></p>",
test_renderer(main).display_content
x_test_renderer(main).display_content
assert_equal "<p>link to <a class='existingWikiWord' href='../published/HomePage'>Home Page</a></p>",
test_renderer(main).display_published
x_test_renderer(main).display_published
assert_equal "<p>link to <a class='existingWikiWord' href='HomePage.html'>Home Page</a></p>",
test_renderer(main).display_content_for_export
x_test_renderer(main).display_content_for_export
end
def test_rendering_included_page_backslashes_in_equations
included = @web.add_page('Included', '\\\\ $\begin{matrix} a \\\\ b\end{matrix}$', Time.now, 'AnAuthor', test_renderer)
main = @web.add_page('Main', '[[!include Included]]', Time.now, 'AnAuthor', test_renderer)
included = @web.add_page('Included', '\\\\ $\begin{matrix} a \\\\ b\end{matrix}$', Time.now, 'AnAuthor', x_test_renderer)
main = @web.add_page('Main', '[[!include Included]]', Time.now, 'AnAuthor', x_test_renderer)
assert_equal "<p>\\ <math class='maruku-mathml' display='inline' " +
"xmlns='http://www.w3.org/1998/Math/MathML'><mrow><mtable rowspacing='0.5ex'>" +
"<mtr><mtd><mi>a</mi></mtd></mtr> <mtr><mtd><mi>b</mi></mtd></mtr></mtable>" +
"</mrow></math></p>",
test_renderer(main).display_content
x_test_renderer(main).display_content
end
private
def add_sample_pages
@in_love = @web.add_page('EverBeenInLove', 'Who am I me',
Time.local(2004, 4, 4, 16, 50), 'DavidHeinemeierHansson', test_renderer)
Time.local(2004, 4, 4, 16, 50), 'DavidHeinemeierHansson', x_test_renderer)
@hated = @web.add_page('EverBeenHated', 'I am me EverBeenHated',
Time.local(2004, 4, 4, 16, 51), 'DavidHeinemeierHansson', test_renderer)
Time.local(2004, 4, 4, 16, 51), 'DavidHeinemeierHansson', x_test_renderer)
end
def assert_markup_parsed_as(expected_output, input)
revision = Revision.new(:page => @page, :content => input, :author => Author.new('AnAuthor'))
assert_equal expected_output, test_renderer(revision).display_content(true), 'Rendering output not as expected'
assert_equal expected_output, x_test_renderer(revision).display_content(true), 'Rendering output not as expected'
end
def assert_match_markup_parsed_as(expected_output, input)
revision = Revision.new(:page => @page, :content => input, :author => Author.new('AnAuthor'))
assert_match expected_output, test_renderer(revision).display_content, 'Rendering output not as expected'
assert_match expected_output, x_test_renderer(revision).display_content, 'Rendering output not as expected'
end
def rendered_content(page)
test_renderer(page.revisions.last).display_content
x_test_renderer(page.revisions.last).display_content
end
end

View file

@ -33,7 +33,7 @@ class PageTest < ActiveSupport::TestCase
def test_revise
@page.revise('HisWay would be MyWay in kinda lame', @page.name, Time.local(2004, 4, 4, 16, 52),
'MarianneSyhler', test_renderer)
'MarianneSyhler', x_test_renderer)
@page.reload
assert_equal 2, @page.revisions.length, 'Should have two revisions'
@ -45,14 +45,14 @@ class PageTest < ActiveSupport::TestCase
def test_revise_continous_revision
@page.revise('HisWay would be MyWay in kinda lame', @page.name, Time.local(2004, 4, 4, 16, 55),
'MarianneSyhler', test_renderer)
'MarianneSyhler', x_test_renderer)
@page.reload
assert_equal 2, @page.revisions.length
assert_equal 'HisWay would be MyWay in kinda lame', @page.content
# consecutive revision by the same author within 30 minutes doesn't create a new revision
@page.revise('HisWay would be MyWay in kinda update', @page.name, Time.local(2004, 4, 4, 16, 57),
'MarianneSyhler', test_renderer)
'MarianneSyhler', x_test_renderer)
@page.reload
assert_equal 2, @page.revisions.length
assert_equal 'HisWay would be MyWay in kinda update', @page.content
@ -60,7 +60,7 @@ class PageTest < ActiveSupport::TestCase
# but consecutive revision by another author results in a new revision
@page.revise('HisWay would be MyWay in the house', @page.name, Time.local(2004, 4, 4, 16, 58),
'DavidHeinemeierHansson', test_renderer)
'DavidHeinemeierHansson', x_test_renderer)
@page.reload
assert_equal 3, @page.revisions.length
assert_equal 'HisWay would be MyWay in the house', @page.content
@ -68,14 +68,14 @@ class PageTest < ActiveSupport::TestCase
# consecutive update after 30 minutes since the last one also creates a new revision,
# even when it is by the same author
@page.revise('HisWay would be MyWay in my way', @page.name, Time.local(2004, 4, 4, 17, 30),
'DavidHeinemeierHansson', test_renderer)
'DavidHeinemeierHansson', x_test_renderer)
@page.reload
assert_equal 4, @page.revisions.length
end
def test_change_name
@page.revise('HisWay would be MyWay in my way', 'SecondPage', Time.local(2004, 4, 5, 17, 56),
'MarianneSyhler', test_renderer)
'MarianneSyhler', x_test_renderer)
@page.reload
assert_equal "Second Page", @page.plain_name
@ -91,7 +91,7 @@ class PageTest < ActiveSupport::TestCase
revisions_number_before = @page.revisions.size
assert_raises(Instiki::ValidationError) {
@page.revise(@page.current_revision.content, @page.name, Time.now, 'AlexeyVerkhovsky', test_renderer)
@page.revise(@page.current_revision.content, @page.name, Time.now, 'AlexeyVerkhovsky', x_test_renderer)
}
assert_equal last_revision_before, @page.current_revision(true)
@ -102,7 +102,7 @@ class PageTest < ActiveSupport::TestCase
web = Web.find(1)
new_page = Page.new(:web => web, :name => 'NewPage')
new_page.revise('Reference to WantedPage, and to WantedPage2', 'NewPage', Time.now, 'AlexeyVerkhovsky',
test_renderer)
x_test_renderer)
references = new_page.wiki_references(true)
assert_equal 2, references.size
@ -112,7 +112,7 @@ class PageTest < ActiveSupport::TestCase
assert_equal WikiReference::WANTED_PAGE, references[1].link_type
wanted_page = Page.new(:web => web, :name => 'WantedPage')
wanted_page.revise('And here it is!', 'WantedPage', Time.now, 'AlexeyVerkhovsky', test_renderer)
wanted_page.revise('And here it is!', 'WantedPage', Time.now, 'AlexeyVerkhovsky', x_test_renderer)
# link type stored for NewPage -> WantedPage reference should change from WANTED to LINKED
# reference NewPage -> WantedPage2 should remain the same
@ -128,7 +128,7 @@ class PageTest < ActiveSupport::TestCase
web = Web.find(1)
new_page = Page.new(:web => web, :name => 'NewPage')
new_page.revise('Reference to HappyPage, and to WantedPage2', 'NewPage', Time.local(2004, 4, 5, 17, 56), 'AlexeyVerkhovsky',
test_renderer)
x_test_renderer)
references = new_page.wiki_references(true)
assert_equal 2, references.size
@ -140,7 +140,7 @@ class PageTest < ActiveSupport::TestCase
assert_equal ["HappyPage", "HisWay", "OverThere", "WantedPage2"], wanted_pages
my_page = Page.new(:web => web, :name => 'MyPage')
my_page.revise("[[!redirects HappyPage]]\nAnd here it is!", 'MyPage', Time.now, 'AlexeyVerkhovsky', test_renderer)
my_page.revise("[[!redirects HappyPage]]\nAnd here it is!", 'MyPage', Time.now, 'AlexeyVerkhovsky', x_test_renderer)
my_references = my_page.wiki_references(true)
assert_equal 1, my_references.size
assert_equal 'HappyPage', my_references[0].referenced_name
@ -152,7 +152,7 @@ class PageTest < ActiveSupport::TestCase
# reference NewPage -> WantedPage2 should remain the same
references = new_page.wiki_references #(true)
assert_match( "Reference to <a class='existingWikiWord' href='\.\./show/MyPage'>Happy Page</a>",
test_renderer(new_page.revisions.last).display_content(true) )
x_test_renderer(new_page.revisions.last).display_content(true) )
assert_equal 2, references.size
assert_equal 'HappyPage', references[0].referenced_name
# Doesn't work, since picking up the change in wiki_references requires a database query.
@ -163,12 +163,12 @@ class PageTest < ActiveSupport::TestCase
assert_equal ["HisWay", "OverThere", "WantedPage2"], wanted_pages
new_page.revise('Reference to HappyPage and to WantedPage2.pdf and [[foo.pdf]]', 'NewPage', Time.now, 'AlexeyVerkhovsky',
test_renderer)
x_test_renderer)
references = new_page.wiki_references(true)
assert_equal( "<p>Reference to <a class='existingWikiWord' href='\.\./show/MyPage'>Happy Page</a>" +
" and to <span class='newWikiWord'>Wanted Page2<a href='../show/WantedPage2'>?</a></span>.pdf " +
"and <span class='wikilink-error'><b>Illegal link (target contains a &#39;.&#39;):</b> foo.pdf</span></p>",
test_renderer(new_page.revisions.last).display_content(true) )
x_test_renderer(new_page.revisions.last).display_content(true) )
assert_equal 3, references.size
# now it works.
assert_equal 'HappyPage', references[0].referenced_name
@ -182,11 +182,11 @@ class PageTest < ActiveSupport::TestCase
end
def test_rollback
@page.revise("spot two", @page.name, Time.now, "David", test_renderer)
@page.revise("spot three", @page.name, Time.now + 2000, "David", test_renderer)
@page.revise("spot two", @page.name, Time.now, "David", x_test_renderer)
@page.revise("spot three", @page.name, Time.now + 2000, "David", x_test_renderer)
assert_equal 3, @page.revisions(true).length, "Should have three revisions"
@page.current_revision(true)
@page.rollback(0, Time.now, '127.0.0.1', test_renderer)
@page.rollback(0, Time.now, '127.0.0.1', x_test_renderer)
assert_equal "HisWay would be MyWay $\\sin(x)\\begin{svg}<svg/>\\end{svg}\\includegraphics[width=3em]{foo}$ in kinda ThatWay in HisWay though MyWay \\\\OverThere -- see SmartEngine in that SmartEngineGUI", @page.current_revision(true).content
end
end

View file

@ -61,9 +61,9 @@ class WebTest < ActiveSupport::TestCase
def test_new_page_linked_from_mother_page
# this was a bug in revision 204
home = @web.add_page('HomePage', 'This page refers to AnotherPage',
Time.local(2004, 4, 4, 16, 50), 'Alexey Verkhovsky', test_renderer)
Time.local(2004, 4, 4, 16, 50), 'Alexey Verkhovsky', x_test_renderer)
@web.add_page('AnotherPage', 'This is \AnotherPage',
Time.local(2004, 4, 4, 16, 51), 'Alexey Verkhovsky', test_renderer)
Time.local(2004, 4, 4, 16, 51), 'Alexey Verkhovsky', x_test_renderer)
@web.pages(true)
assert_equal [home], @web.select.pages_that_link_to('AnotherPage')
@ -73,13 +73,13 @@ class WebTest < ActiveSupport::TestCase
add_sample_pages
home = @web.add_page('HomePage',
'This is a home page, it should not be an orphan',
Time.local(2004, 4, 4, 16, 50), 'AlexeyVerkhovsky', test_renderer)
Time.local(2004, 4, 4, 16, 50), 'AlexeyVerkhovsky', x_test_renderer)
author = @web.add_page('AlexeyVerkhovsky',
'This is an author page, it should not be an orphan',
Time.local(2004, 4, 4, 16, 50), 'AlexeyVerkhovsky', test_renderer)
Time.local(2004, 4, 4, 16, 50), 'AlexeyVerkhovsky', x_test_renderer)
self_linked = @web.add_page('SelfLinked',
"I am SelfLinked and link to EverBeenInLove\ncategory: fubar",
Time.local(2004, 4, 4, 16, 50), 'AnonymousCoward', test_renderer)
Time.local(2004, 4, 4, 16, 50), 'AnonymousCoward', x_test_renderer)
# page that links to itself, and nobody else links to it must be an orphan
assert_equal ['EverBeenHated', 'SelfLinked'],
@ -102,8 +102,8 @@ class WebTest < ActiveSupport::TestCase
def add_sample_pages
@in_love = @web.add_page('EverBeenInLove', "Who am I me\ncategory: fubar",
Time.local(2004, 4, 4, 16, 50), 'DavidHeinemeierHansson', test_renderer)
Time.local(2004, 4, 4, 16, 50), 'DavidHeinemeierHansson', x_test_renderer)
@hated = @web.add_page('EverBeenHated', 'I am me EverBeenHated',
Time.local(2004, 4, 4, 16, 51), 'DavidHeinemeierHansson', test_renderer)
Time.local(2004, 4, 4, 16, 51), 'DavidHeinemeierHansson', x_test_renderer)
end
end

View file

@ -1,3 +1,7 @@
*2.3.5 (November 25, 2009)*
* Minor Bug Fixes and deprecation warnings
*2.3.4 (September 4, 2009)*
* Minor bug fixes.

View file

@ -54,7 +54,7 @@ spec = Gem::Specification.new do |s|
s.rubyforge_project = "actionmailer"
s.homepage = "http://www.rubyonrails.org"
s.add_dependency('actionpack', '= 2.3.4' + PKG_BUILD)
s.add_dependency('actionpack', '= 2.3.5' + PKG_BUILD)
s.has_rdoc = true
s.requirements << 'none'

View file

@ -43,6 +43,7 @@ module Racc
class Parser
old_verbose, $VERBOSE = $VERBOSE, nil
Racc_Runtime_Version = '1.4.5'
Racc_Runtime_Revision = '$Revision: 1.7 $'.split[1]
@ -71,6 +72,7 @@ module Racc
Racc_Runtime_Core_Revision = Racc_Runtime_Core_Revision_R
Racc_Runtime_Type = 'ruby'
end
$VERBOSE = old_verbose
def Parser.racc_runtime_type
Racc_Runtime_Type

View file

@ -2,7 +2,7 @@ module ActionMailer
module VERSION #:nodoc:
MAJOR = 2
MINOR = 3
TINY = 4
TINY = 5
STRING = [MAJOR, MINOR, TINY].join('.')
end

View file

@ -1 +1,2 @@
require 'action_mailer'
ActiveSupport::Deprecation.warn 'require "actionmailer" is deprecated and will be removed in Rails 3. Use require "action_mailer" instead.'

View file

@ -1,5 +1,5 @@
module ExampleHelper
def example_format(text)
"<em><strong><small>#{text}</small></strong></em>"
"<em><strong><small>#{h(text)}</small></strong></em>".html_safe!
end
end

View file

@ -570,7 +570,9 @@ class ActionMailerTest < Test::Unit::TestCase
mail = TestMailer.create_signed_up(@recipient)
logger = mock()
logger.expects(:info).with("Sent mail to #{@recipient}")
logger.expects(:debug).with("\n#{mail.encoded}")
logger.expects(:debug).with() do |logged_text|
logged_text =~ /\[Signed up\] Welcome/
end
TestMailer.logger = logger
TestMailer.deliver_signed_up(@recipient)
end

View file

@ -1,3 +1,15 @@
*2.3.5 (November 25, 2009)*
* Minor Bug Fixes and deprecation warnings
* Ruby 1.9 Support
* Fix filtering parameters when there are Fixnum or other un-dupable values.
* Improvements to ActionView::TestCase
* Compatiblity with the rails_xss plugin
*2.3.4 (September 4, 2009)*
* Sanitize multibyte strings before escaping them with escape_once. CVE-2009-3009

View file

@ -79,7 +79,7 @@ spec = Gem::Specification.new do |s|
s.has_rdoc = true
s.requirements << 'none'
s.add_dependency('activesupport', '= 2.3.4' + PKG_BUILD)
s.add_dependency('activesupport', '= 2.3.5' + PKG_BUILD)
s.add_dependency('rack', '~> 1.0.0')
s.require_path = 'lib'

View file

@ -1,87 +0,0 @@
$:.push File.join(File.dirname(__FILE__), "..", "lib")
$:.push File.join(File.dirname(__FILE__), "..", "..", "activesupport", "lib")
require "action_controller"
class Runner
def initialize(app, output)
@app, @output = app, output
end
def puts(*)
super if @output
end
def call(env)
env['n'].to_i.times { @app.call(env) }
@app.call(env).tap { |response| report(env, response) }
end
def report(env, response)
if ENV["DEBUG"]
out = env['rack.errors']
p response.headers
out.puts response.status, response.headers.to_yaml, '---'
response.body.each { |part| out.puts part }
out.puts '---'
end
end
def self.puts(*)
super if @output
end
def self.run(app, n, label = nil, uri = "/", output = true)
@output = output
puts label, '=' * label.size if label
env = Rack::MockRequest.env_for(uri).merge('n' => n, 'rack.input' => StringIO.new(''), 'rack.errors' => $stdout)
t = Benchmark.realtime { new(app, output).call(env) }
puts "%d ms / %d req = %.1f usec/req" % [10**3 * t, n, 10**6 * t / n]
puts
end
end
N = (ENV['N'] || 1000).to_i
class BasePostController < ActionController::Base
append_view_path "#{File.dirname(__FILE__)}/views"
def index
render :text => 'Hello'
end
def partial
render :partial => "/partial"
end
def many_partials
render :partial => "/many_partials"
end
def partial_collection
render :partial => "/collection", :collection => [1,2,3,4,5,6,7,8,9,10]
end
def show_template
render :template => "template"
end
end
# p BasePostController.call(Rack::MockRequest.env_for("/?action=index").merge("REQUEST_URI" => "/")).body
Runner.run(BasePostController, N, 'index', "/?action=index", false)
Runner.run(BasePostController, N, 'partial', "/?action=partial", false)
Runner.run(BasePostController, N, 'many partials', "/?action=many_partials", false)
Runner.run(BasePostController, N, 'collection', "/?action=partial_collection", false)
Runner.run(BasePostController, N, 'template', "/?action=show_template", false)
(ENV["M"] || 1).to_i.times do
Runner.run(BasePostController, N, 'index', "/?action=index")
Runner.run(BasePostController, N, 'partial', "/?action=partial")
Runner.run(BasePostController, N, 'many partials', "/?action=many_partials")
Runner.run(BasePostController, N, 'collection', "/?action=partial_collection")
Runner.run(BasePostController, N, 'template', "/?action=show_template")
end
# Runner.run(BasePostController.action(:many_partials), N, 'index')
# Runner.run(BasePostController.action(:many_partials), N, 'many_partials')
# Runner.run(BasePostController.action(:partial_collection), N, 'collection')
# Runner.run(BasePostController.action(:show_template), N, 'template')

View file

@ -1 +0,0 @@
<%= collection %>

View file

@ -1 +0,0 @@
Hello

View file

@ -1,10 +0,0 @@
<%= render :partial => '/hello' %>
<%= render :partial => '/hello' %>
<%= render :partial => '/hello' %>
<%= render :partial => '/hello' %>
<%= render :partial => '/hello' %>
<%= render :partial => '/hello' %>
<%= render :partial => '/hello' %>
<%= render :partial => '/hello' %>
<%= render :partial => '/hello' %>
<%= render :partial => '/hello' %>

View file

@ -1,10 +0,0 @@
<%= "Hello" %>
<%= "Hello" %>
<%= "Hello" %>
<%= "Hello" %>
<%= "Hello" %>
<%= "Hello" %>
<%= "Hello" %>
<%= "Hello" %>
<%= "Hello" %>
<%= "Hello" %>

View file

@ -1 +0,0 @@
+ <%= yield %> +

View file

@ -1 +0,0 @@
Hello <%= yield %> Goodbye

View file

@ -1 +0,0 @@
Hello

View file

@ -37,6 +37,7 @@ begin
rescue Gem::LoadError
require 'action_controller/vendor/rack-1.1.pre/rack'
end
require 'action_controller/cgi_ext'
module ActionController
# TODO: Review explicit to see if they will automatically be handled by
@ -74,6 +75,7 @@ module ActionController
autoload :SessionManagement, 'action_controller/session_management'
autoload :StatusCodes, 'action_controller/status_codes'
autoload :Streaming, 'action_controller/streaming'
autoload :StringCoercion, 'action_controller/string_coercion'
autoload :TestCase, 'action_controller/test_case'
autoload :TestProcess, 'action_controller/test_process'
autoload :Translation, 'action_controller/translation'

View file

@ -1,6 +1,18 @@
module ActionController
module Assertions
module DomAssertions
def self.strip_whitespace!(nodes)
nodes.reject! do |node|
if node.is_a?(HTML::Text)
node.content.strip!
node.content.empty?
else
strip_whitespace! node.children
false
end
end
end
# Test two HTML strings for equivalency (e.g., identical up to reordering of attributes)
#
# ==== Examples
@ -12,13 +24,15 @@ module ActionController
clean_backtrace do
expected_dom = HTML::Document.new(expected).root
actual_dom = HTML::Document.new(actual).root
full_message = build_message(message, "<?> expected to be == to\n<?>.", expected_dom.to_s, actual_dom.to_s)
DomAssertions.strip_whitespace!(expected_dom.children)
DomAssertions.strip_whitespace!(actual_dom.children)
full_message = build_message(message, "<?> expected but was\n<?>.", expected_dom.to_s, actual_dom.to_s)
assert_block(full_message) { expected_dom == actual_dom }
end
end
# The negated form of +assert_dom_equivalent+.
# The negated form of +assert_dom_equal+.
#
# ==== Examples
#
@ -29,8 +43,10 @@ module ActionController
clean_backtrace do
expected_dom = HTML::Document.new(expected).root
actual_dom = HTML::Document.new(actual).root
full_message = build_message(message, "<?> expected to be != to\n<?>.", expected_dom.to_s, actual_dom.to_s)
DomAssertions.strip_whitespace!(expected_dom.children)
DomAssertions.strip_whitespace!(actual_dom.children)
full_message = build_message(message, "<?> expected to be != to\n<?>.", expected_dom.to_s, actual_dom.to_s)
assert_block(full_message) { expected_dom != actual_dom }
end
end

View file

@ -16,7 +16,7 @@ module ActionController
#
# Use +css_select+ to select elements without making an assertions, either
# from the response HTML or elements selected by the enclosing assertion.
#
#
# In addition to HTML responses, you can make the following assertions:
# * +assert_select_rjs+ - Assertions on HTML content of RJS update and insertion operations.
# * +assert_select_encoded+ - Assertions on HTML encoded inside XML, for example for dealing with feed item descriptions.
@ -24,6 +24,12 @@ module ActionController
#
# Also see HTML::Selector to learn how to use selectors.
module SelectorAssertions
def initialize(*args)
super
@selected = nil
end
# :call-seq:
# css_select(selector) => array
# css_select(element, selector) => array
@ -53,8 +59,8 @@ module ActionController
# end
#
# # Selects all list items in unordered lists
# items = css_select("ul>li")
#
# items = css_select("ul>li")
#
# # Selects all form tags and then all inputs inside the form
# forms = css_select("form")
# forms.each do |form|
@ -212,7 +218,7 @@ module ActionController
# Otherwise just operate on the response document.
root = response_from_page_or_rjs
end
# First or second argument is the selector: string and we pass
# all remaining arguments. Array and we pass the argument. Also
# accepts selector itself.
@ -225,7 +231,7 @@ module ActionController
selector = arg
else raise ArgumentError, "Expecting a selector as the first argument"
end
# Next argument is used for equality tests.
equals = {}
case arg = args.shift
@ -315,10 +321,10 @@ module ActionController
# Returns all matches elements.
matches
end
def count_description(min, max) #:nodoc:
pluralize = lambda {|word, quantity| word << (quantity == 1 ? '' : 's')}
if min && max && (max != min)
"between #{min} and #{max} elements"
elsif min && !(min == 1 && max == 1)
@ -327,7 +333,7 @@ module ActionController
"at most #{max} #{pluralize['element', max]}"
end
end
# :call-seq:
# assert_select_rjs(id?) { |elements| ... }
# assert_select_rjs(statement, id?) { |elements| ... }
@ -344,7 +350,7 @@ module ActionController
# that update or insert an element with that identifier.
#
# Use the first argument to narrow down assertions to only statements
# of that type. Possible values are <tt>:replace</tt>, <tt>:replace_html</tt>,
# of that type. Possible values are <tt>:replace</tt>, <tt>:replace_html</tt>,
# <tt>:show</tt>, <tt>:hide</tt>, <tt>:toggle</tt>, <tt>:remove</tt> and
# <tt>:insert_html</tt>.
#
@ -488,7 +494,7 @@ module ActionController
# end
# end
# end
#
#
#
# # Selects all paragraph tags from within the description of an RSS feed
# assert_select_feed :rss, 2.0 do

View file

@ -502,7 +502,7 @@ module ActionController #:nodoc:
end
elsif block_given?
key = key.dup
value = value.dup if value
value = value.dup if value.duplicable?
yield key, value
filtered_parameters[key] = value
else

View file

@ -22,6 +22,7 @@ module ActionController #:nodoc:
# ActionController::Base.cache_store = :file_store, "/path/to/cache/directory"
# ActionController::Base.cache_store = :drb_store, "druby://localhost:9192"
# ActionController::Base.cache_store = :mem_cache_store, "localhost"
# ActionController::Base.cache_store = :mem_cache_store, Memcached::Rails.new("localhost:11211")
# ActionController::Base.cache_store = MyOwnStore.new("parameter")
module Caching
autoload :Actions, 'action_controller/caching/actions'

View file

@ -87,8 +87,9 @@ module ActionController #:nodoc:
def delete(key, options = {})
options.symbolize_keys!
options[:path] = "/" unless options.has_key?(:path)
super(key.to_s)
value = super(key.to_s)
@controller.response.delete_cookie(key, options)
value
end
end
end

View file

@ -227,9 +227,9 @@ module ActionController
end
def decode_credentials(header)
header.to_s.gsub(/^Digest\s+/,'').split(',').inject({}) do |hash, pair|
header.to_s.gsub(/^Digest\s+/,'').split(',').inject({}.with_indifferent_access) do |hash, pair|
key, value = pair.split('=', 2)
hash[key.strip.to_sym] = value.to_s.gsub(/^"|"$/,'').gsub(/'/, '')
hash[key.strip] = value.to_s.gsub(/^"|"$/,'').gsub(/'/, '')
hash
end
end
@ -289,6 +289,7 @@ module ActionController
# allow a user to use new nonce without prompting user again for their
# username and password.
def validate_nonce(request, value, seconds_to_timeout=5*60)
return false if value.nil?
t = Base64.decode64(value).split(":").first.to_i
nonce(t) == value && (t - Time.now.to_i).abs <= seconds_to_timeout
end

View file

@ -1,6 +1,7 @@
require 'stringio'
require 'uri'
require 'active_support/test_case'
require 'action_controller/rack_lint_patch'
module ActionController
module Integration #:nodoc:
@ -268,7 +269,9 @@ module ActionController
env["QUERY_STRING"] ||= ""
data = data.is_a?(IO) ? data : StringIO.new(data || '')
data ||= ''
data.force_encoding(Encoding::ASCII_8BIT) if data.respond_to?(:force_encoding)
data = data.is_a?(IO) ? data : StringIO.new(data)
env.update(
"REQUEST_METHOD" => method.to_s.upcase,
@ -476,6 +479,11 @@ EOF
end
module Runner
def initialize(*args)
super
@integration_session = nil
end
# Reset the current session. This is useful for testing multiple sessions
# in a single test case.
def reset!
@ -543,8 +551,12 @@ EOF
# Delegate unhandled messages to the current session instance.
def method_missing(sym, *args, &block)
reset! unless @integration_session
returning @integration_session.__send__(sym, *args, &block) do
copy_session_variables!
if @integration_session.respond_to?(sym)
returning @integration_session.__send__(sym, *args, &block) do
copy_session_variables!
end
else
super
end
end
end

View file

@ -194,6 +194,11 @@ module ActionController #:nodoc:
end
end
def initialize(*args)
super
@real_format = nil
end
# Returns the name of the active layout. If the layout was specified as a method reference (through a symbol), this method
# is called and the return value is used. Likewise if the layout was specified as an inline method (through a proc or method
# object). If the layout was defined without a directory, layouts is assumed. So <tt>layout "weblog/standard"</tt> will return
@ -221,7 +226,7 @@ module ActionController #:nodoc:
end
def find_layout(layout, format, html_fallback=false) #:nodoc:
view_paths.find_template(layout.to_s =~ /layouts\// ? layout : "layouts/#{layout}", format, html_fallback)
view_paths.find_template(layout.to_s =~ /\A\/|layouts\// ? layout : "layouts/#{layout}", format, html_fallback)
rescue ActionView::MissingTemplate
raise if Mime::Type.lookup_by_extension(format.to_s).html?
end

View file

@ -10,3 +10,5 @@ use lambda { ActionController::Base.session_store },
use "ActionController::ParamsParser"
use "Rack::MethodOverride"
use "Rack::Head"
use "ActionController::StringCoercion"

View file

@ -76,8 +76,7 @@ module ActionController
record_or_hash_or_array = record_or_hash_or_array[0] if record_or_hash_or_array.size == 1
end
record = extract_record(record_or_hash_or_array)
namespace = extract_namespace(record_or_hash_or_array)
record = extract_record(record_or_hash_or_array)
args = case record_or_hash_or_array
when Hash; [ record_or_hash_or_array ]
@ -98,8 +97,7 @@ module ActionController
end
args.delete_if {|arg| arg.is_a?(Symbol) || arg.is_a?(String)}
named_route = build_named_route_call(record_or_hash_or_array, namespace, inflection, options)
named_route = build_named_route_call(record_or_hash_or_array, inflection, options)
url_options = options.except(:action, :routing_type)
unless url_options.empty?
@ -153,7 +151,7 @@ module ActionController
options[:routing_type] || :url
end
def build_named_route_call(records, namespace, inflection, options = {})
def build_named_route_call(records, inflection, options = {})
unless records.is_a?(Array)
record = extract_record(records)
route = ''
@ -163,7 +161,7 @@ module ActionController
if parent.is_a?(Symbol) || parent.is_a?(String)
string << "#{parent}_"
else
string << "#{RecordIdentifier.__send__("plural_class_name", parent)}".singularize
string << RecordIdentifier.__send__("plural_class_name", parent).singularize
string << "_"
end
end
@ -172,12 +170,12 @@ module ActionController
if record.is_a?(Symbol) || record.is_a?(String)
route << "#{record}_"
else
route << "#{RecordIdentifier.__send__("plural_class_name", record)}"
route << RecordIdentifier.__send__("plural_class_name", record)
route = route.singularize if inflection == :singular
route << "_"
end
action_prefix(options) + namespace + route + routing_type(options).to_s
action_prefix(options) + route + routing_type(options).to_s
end
def extract_record(record_or_hash_or_array)
@ -187,18 +185,5 @@ module ActionController
else record_or_hash_or_array
end
end
# Remove the first symbols from the array and return the url prefix
# implied by those symbols.
def extract_namespace(record_or_hash_or_array)
return "" unless record_or_hash_or_array.is_a?(Array)
namespace_keys = []
while (key = record_or_hash_or_array.first) && key.is_a?(String) || key.is_a?(Symbol)
namespace_keys << record_or_hash_or_array.shift
end
namespace_keys.map {|k| "#{k}_"}.join
end
end
end

View file

@ -0,0 +1,36 @@
# Rack 1.0 does not allow string subclass body. This does not play well with our ActionView::SafeBuffer.
# The next release of Rack will be allowing string subclass body - http://github.com/rack/rack/commit/de668df02802a0335376a81ba709270e43ba9d55
# TODO : Remove this monkey patch after the next release of Rack
module RackLintPatch
module AllowStringSubclass
def self.included(base)
base.send :alias_method, :each, :each_with_hack
end
def each_with_hack
@closed = false
@body.each { |part|
assert("Body yielded non-string value #{part.inspect}") {
part.kind_of?(String)
}
yield part
}
if @body.respond_to?(:to_path)
assert("The file identified by body.to_path does not exist") {
::File.exist? @body.to_path
}
end
end
end
begin
app = proc {|env| [200, {"Content-Type" => "text/plain", "Content-Length" => "12"}, [Class.new(String).new("Hello World!")]] }
response = Rack::MockRequest.new(Rack::Lint.new(app)).get('/')
rescue Rack::Lint::LintError => e
raise(e) unless e.message =~ /Body yielded non-string value/
Rack::Lint.send :include, AllowStringSubclass
end
end

View file

@ -89,9 +89,13 @@ module ActionController #:nodoc:
request.method == :get ||
request.xhr? ||
!verifiable_request_format? ||
form_authenticity_token == params[request_forgery_protection_token]
form_authenticity_token == form_authenticity_param
end
def form_authenticity_param
params[request_forgery_protection_token]
end
def verifiable_request_format?
!request.content_type.nil? && request.content_type.verify_request?
end

View file

@ -47,7 +47,8 @@ module ActionController # :nodoc:
@block = nil
@body = "",
@session, @assigns = [], []
@session = []
@assigns = []
end
def location; headers['Location'] end

View file

@ -0,0 +1,29 @@
module ActionController
class StringCoercion
class UglyBody < ActiveSupport::BasicObject
def initialize(body)
@body = body
end
def each
@body.each do |part|
yield part.to_s
end
end
private
def method_missing(*args, &block)
@body.__send__(*args, &block)
end
end
def initialize(app)
@app = app
end
def call(env)
status, headers, body = @app.call(env)
[status, headers, UglyBody.new(body)]
end
end
end

View file

@ -105,6 +105,11 @@ module ActionController
class TestCase < ActiveSupport::TestCase
include TestProcess
def initialize(*args)
super
@controller = nil
end
module Assertions
%w(response selector tag dom routing model).each do |kind|
include ActionController::Assertions.const_get("#{kind.camelize}Assertions")
@ -195,7 +200,7 @@ module ActionController
@controller.send(:initialize_current_url)
end
end
# Cause the action to be rescued according to the regular rules for rescue_action when the visitor is not local
def rescue_action_in_public!
@request.remote_addr = '208.77.188.166' # example.com

View file

@ -91,7 +91,7 @@ module ActionController #:nodoc:
@path || super()
end
def assign_parameters(controller_path, action, parameters)
def assign_parameters(controller_path, action, parameters = {})
parameters = parameters.symbolize_keys.merge(:controller => controller_path, :action => action)
extra_keys = ActionController::Routing::Routes.extra_keys(parameters)
non_path_parameters = get? ? query_parameters : request_parameters

View file

@ -1,12 +1,12 @@
module ActionController
module Translation
def translate(*args)
I18n.translate *args
I18n.translate(*args)
end
alias :t :translate
def localize(*args)
I18n.localize *args
I18n.localize(*args)
end
alias :l :localize
end

View file

@ -3,14 +3,14 @@ module ActionController
def self.included(base)
base.class_eval do
attr_accessor :original_path, :content_type
alias_method :local_path, :path
alias_method :local_path, :path if method_defined?(:path)
end
end
def self.extended(object)
object.class_eval do
attr_accessor :original_path, :content_type
alias_method :local_path, :path
alias_method :local_path, :path if method_defined?(:path)
end
end

View file

@ -162,7 +162,7 @@ module HTML #:nodoc:
end
closing = ( scanner.scan(/\//) ? :close : nil )
return Text.new(parent, line, pos, content) unless name = scanner.scan(/[\w:-]+/)
return Text.new(parent, line, pos, content) unless name = scanner.scan(/[-:\w\x00-\x09\x0b-\x0c\x0e-\x1f]+/)
name.downcase!
unless closing

View file

@ -2,7 +2,7 @@ module ActionPack #:nodoc:
module VERSION #:nodoc:
MAJOR = 2
MINOR = 3
TINY = 4
TINY = 5
STRING = [MAJOR, MINOR, TINY].join('.')
end

View file

@ -49,10 +49,10 @@ module ActionView
autoload :TemplateHandler, 'action_view/template_handler'
autoload :TemplateHandlers, 'action_view/template_handlers'
autoload :Helpers, 'action_view/helpers'
autoload :SafeBuffer, 'action_view/safe_buffer'
end
class ERB
autoload :Util, 'action_view/erb/util'
end
require 'action_view/erb/util'
I18n.load_path << "#{File.dirname(__FILE__)}/action_view/locale/en.yml"

View file

@ -187,13 +187,18 @@ module ActionView #:nodoc:
@@cache_template_loading = nil
cattr_accessor :cache_template_loading
# :nodoc:
def self.xss_safe?
false
end
def self.cache_template_loading?
ActionController::Base.allow_concurrency || (cache_template_loading.nil? ? !ActiveSupport::Dependencies.load? : cache_template_loading)
end
attr_internal :request
delegate :request_forgery_protection_token, :template, :params, :session, :cookies, :response, :headers,
delegate :request_forgery_protection_token, :params, :session, :cookies, :response, :headers,
:flash, :logger, :action_name, :controller_name, :to => :controller
module CompiledTemplates #:nodoc:

View file

@ -18,6 +18,12 @@ class ERB
s.to_s.gsub(/[&"><]/) { |special| HTML_ESCAPE[special] }
end
undef :h
alias h html_escape
module_function :html_escape
module_function :h
# A utility method for escaping HTML entities in JSON strings.
# This method is also aliased as <tt>j</tt>.
#

View file

@ -14,6 +14,7 @@ module ActionView #:nodoc:
autoload :JavaScriptHelper, 'action_view/helpers/javascript_helper'
autoload :NumberHelper, 'action_view/helpers/number_helper'
autoload :PrototypeHelper, 'action_view/helpers/prototype_helper'
autoload :RawOutputHelper, 'action_view/helpers/raw_output_helper'
autoload :RecordIdentificationHelper, 'action_view/helpers/record_identification_helper'
autoload :RecordTagHelper, 'action_view/helpers/record_tag_helper'
autoload :SanitizeHelper, 'action_view/helpers/sanitize_helper'
@ -45,6 +46,7 @@ module ActionView #:nodoc:
include JavaScriptHelper
include NumberHelper
include PrototypeHelper
include RawOutputHelper
include RecordIdentificationHelper
include RecordTagHelper
include SanitizeHelper

View file

@ -3,7 +3,7 @@ require 'action_view/helpers/form_helper'
module ActionView
class Base
@@field_error_proc = Proc.new{ |html_tag, instance| "<div class=\"fieldWithErrors\">#{html_tag}</div>" }
@@field_error_proc = Proc.new{ |html_tag, instance| "<div class=\"fieldWithErrors\">#{html_tag}</div>".html_safe! }
cattr_accessor :field_error_proc
end
@ -171,7 +171,7 @@ module ActionView
options = params.extract_options!.symbolize_keys
if object = options.delete(:object)
objects = [object].flatten
objects = Array.wrap(object)
else
objects = params.collect {|object_name| instance_variable_get("@#{object_name}") }.compact
end
@ -290,7 +290,7 @@ module ActionView
end
def error_wrapping(html_tag, has_error)
has_error ? Base.field_error_proc.call(html_tag, self) : html_tag
has_error ? Base.field_error_proc.call(html_tag, self).html_safe! : html_tag
end
def error_message

View file

@ -285,7 +285,7 @@ module ActionView
end
javascript_src_tag(joined_javascript_name, options)
else
expand_javascript_sources(sources, recursive).collect { |source| javascript_src_tag(source, options) }.join("\n")
expand_javascript_sources(sources, recursive).collect { |source| javascript_src_tag(source, options) }.join("\n").html_safe!
end
end
@ -434,7 +434,7 @@ module ActionView
end
stylesheet_tag(joined_stylesheet_name, options)
else
expand_stylesheet_sources(sources, recursive).collect { |source| stylesheet_tag(source, options) }.join("\n")
expand_stylesheet_sources(sources, recursive).collect { |source| stylesheet_tag(source, options) }.join("\n").html_safe!
end
end

View file

@ -118,13 +118,13 @@ module ActionView
def content_for(name, content = nil, &block)
ivar = "@content_for_#{name}"
content = capture(&block) if block_given?
instance_variable_set(ivar, "#{instance_variable_get(ivar)}#{content}")
instance_variable_set(ivar, "#{instance_variable_get(ivar)}#{content}".html_safe!)
nil
end
# Use an alternate output buffer for the duration of the block.
# Defaults to a new empty string.
def with_output_buffer(buf = '') #:nodoc:
def with_output_buffer(buf = "") #:nodoc:
self.output_buffer, old_buffer = buf, output_buffer
yield
output_buffer

View file

@ -26,8 +26,10 @@ module ActionView
# 47 hrs, 59 mins, 29 secs <-> 29 days, 23 hrs, 59 mins, 29 secs # => [2..29] days
# 29 days, 23 hrs, 59 mins, 30 secs <-> 59 days, 23 hrs, 59 mins, 29 secs # => about 1 month
# 59 days, 23 hrs, 59 mins, 30 secs <-> 1 yr minus 1 sec # => [2..12] months
# 1 yr <-> 2 yrs minus 1 secs # => about 1 year
# 2 yrs <-> max time or date # => over [2..X] years
# 1 yr <-> 1 yr, 3 months # => about 1 year
# 1 yr, 3 months <-> 1 yr, 9 months # => over 1 year
# 1 yr, 9 months <-> 2 yr minus 1 sec # => almost 2 years
# 2 yrs <-> max time or date # => (same rules as 1 yr)
#
# With <tt>include_seconds</tt> = true and the difference < 1 minute 29 seconds:
# 0-4 secs # => less than 5 seconds
@ -43,17 +45,18 @@ module ActionView
# distance_of_time_in_words(from_time, 50.minutes.from_now) # => about 1 hour
# distance_of_time_in_words(from_time, from_time + 15.seconds) # => less than a minute
# distance_of_time_in_words(from_time, from_time + 15.seconds, true) # => less than 20 seconds
# distance_of_time_in_words(from_time, 3.years.from_now) # => over 3 years
# distance_of_time_in_words(from_time, 3.years.from_now) # => about 3 years
# distance_of_time_in_words(from_time, from_time + 60.hours) # => about 3 days
# distance_of_time_in_words(from_time, from_time + 45.seconds, true) # => less than a minute
# distance_of_time_in_words(from_time, from_time - 45.seconds, true) # => less than a minute
# distance_of_time_in_words(from_time, 76.seconds.from_now) # => 1 minute
# distance_of_time_in_words(from_time, from_time + 1.year + 3.days) # => about 1 year
# distance_of_time_in_words(from_time, from_time + 4.years + 9.days + 30.minutes + 5.seconds) # => over 4 years
# distance_of_time_in_words(from_time, from_time + 3.years + 6.months) # => over 3 years
# distance_of_time_in_words(from_time, from_time + 4.years + 9.days + 30.minutes + 5.seconds) # => about 4 years
#
# to_time = Time.now + 6.years + 19.days
# distance_of_time_in_words(from_time, to_time, true) # => over 6 years
# distance_of_time_in_words(to_time, from_time, true) # => over 6 years
# distance_of_time_in_words(from_time, to_time, true) # => about 6 years
# distance_of_time_in_words(to_time, from_time, true) # => about 6 years
# distance_of_time_in_words(Time.now, Time.now) # => less than a minute
#
def distance_of_time_in_words(from_time, to_time = 0, include_seconds = false, options = {})
@ -81,12 +84,21 @@ module ActionView
when 2..44 then locale.t :x_minutes, :count => distance_in_minutes
when 45..89 then locale.t :about_x_hours, :count => 1
when 90..1439 then locale.t :about_x_hours, :count => (distance_in_minutes.to_f / 60.0).round
when 1440..2879 then locale.t :x_days, :count => 1
when 2880..43199 then locale.t :x_days, :count => (distance_in_minutes / 1440).round
when 1440..2529 then locale.t :x_days, :count => 1
when 2530..43199 then locale.t :x_days, :count => (distance_in_minutes.to_f / 1440.0).round
when 43200..86399 then locale.t :about_x_months, :count => 1
when 86400..525599 then locale.t :x_months, :count => (distance_in_minutes / 43200).round
when 525600..1051199 then locale.t :about_x_years, :count => 1
else locale.t :over_x_years, :count => (distance_in_minutes / 525600).round
when 86400..525599 then locale.t :x_months, :count => (distance_in_minutes.to_f / 43200.0).round
else
distance_in_years = distance_in_minutes / 525600
minute_offset_for_leap_year = (distance_in_years / 4) * 1440
remainder = ((distance_in_minutes - minute_offset_for_leap_year) % 525600)
if remainder < 131400
locale.t(:about_x_years, :count => distance_in_years)
elsif remainder < 394200
locale.t(:over_x_years, :count => distance_in_years)
else
locale.t(:almost_x_years, :count => distance_in_years + 1)
end
end
end
end
@ -904,15 +916,15 @@ module ActionView
class InstanceTag #:nodoc:
def to_date_select_tag(options = {}, html_options = {})
datetime_selector(options, html_options).select_date
datetime_selector(options, html_options).select_date.html_safe!
end
def to_time_select_tag(options = {}, html_options = {})
datetime_selector(options, html_options).select_time
datetime_selector(options, html_options).select_time.html_safe!
end
def to_datetime_select_tag(options = {}, html_options = {})
datetime_selector(options, html_options).select_datetime
datetime_selector(options, html_options).select_datetime.html_safe!
end
private
@ -923,7 +935,7 @@ module ActionView
options[:field_name] = @method_name
options[:include_position] = true
options[:prefix] ||= @object_name
options[:index] = @auto_index if @auto_index && !options.has_key?(:index)
options[:index] = @auto_index if defined?(@auto_index) && @auto_index && !options.has_key?(:index)
options[:datetime_separator] ||= ' &mdash; '
options[:time_separator] ||= ' : '

View file

@ -280,7 +280,7 @@ module ActionView
concat(form_tag(options.delete(:url) || {}, options.delete(:html) || {}))
fields_for(object_name, *(args << options), &proc)
concat('</form>')
concat('</form>'.html_safe!)
end
def apply_form_for_options!(object_or_array, options) #:nodoc:
@ -445,6 +445,15 @@ module ActionView
# <% end %>
# <% end %>
#
# Or a collection to be used:
#
# <% form_for @person, :url => { :action => "update" } do |person_form| %>
# ...
# <% person_form.fields_for :projects, @active_projects do |project_fields| %>
# Name: <%= project_fields.text_field :name %>
# <% end %>
# <% end %>
#
# When projects is already an association on Person you can use
# +accepts_nested_attributes_for+ to define the writer method for you:
#
@ -788,7 +797,7 @@ module ActionView
add_default_name_and_id(options)
hidden = tag("input", "name" => options["name"], "type" => "hidden", "value" => options['disabled'] && checked ? checked_value : unchecked_value)
checkbox = tag("input", options)
hidden + checkbox
(hidden + checkbox).html_safe!
end
def to_boolean_select_tag(options = {})
@ -930,7 +939,7 @@ module ActionView
end
end
(field_helpers - %w(label check_box radio_button fields_for)).each do |selector|
(field_helpers - %w(label check_box radio_button fields_for hidden_field)).each do |selector|
src = <<-end_src
def #{selector}(method, options = {}) # def text_field(method, options = {})
@template.send( # @template.send(
@ -989,6 +998,11 @@ module ActionView
def radio_button(method, tag_value, options = {})
@template.radio_button(@object_name, method, tag_value, objectify_options(options))
end
def hidden_field(method, options = {})
@emitted_hidden_id = true if method == :id
@template.hidden_field(@object_name, method, objectify_options(options))
end
def error_message_on(method, *args)
@template.error_message_on(@object, method, *args)
@ -1002,6 +1016,10 @@ module ActionView
@template.submit_tag(value, options.reverse_merge(:id => "#{object_name}_submit"))
end
def emitted_hidden_id?
@emitted_hidden_id
end
private
def objectify_options(options)
@default_options.merge(options.merge(:object => @object))
@ -1013,18 +1031,21 @@ module ActionView
def fields_for_with_nested_attributes(association_name, args, block)
name = "#{object_name}[#{association_name}_attributes]"
association = @object.send(association_name)
explicit_object = args.first if args.first.respond_to?(:new_record?)
association = args.first
if association.respond_to?(:new_record?)
association = [association] if @object.send(association_name).is_a?(Array)
elsif !association.is_a?(Array)
association = @object.send(association_name)
end
if association.is_a?(Array)
children = explicit_object ? [explicit_object] : association
explicit_child_index = args.last[:child_index] if args.last.is_a?(Hash)
children.map do |child|
association.map do |child|
fields_for_nested_model("#{name}[#{explicit_child_index || nested_child_index(name)}]", child, args, block)
end.join
else
fields_for_nested_model(name, explicit_object || association, args, block)
elsif association
fields_for_nested_model(name, association, args, block)
end
end
@ -1033,8 +1054,8 @@ module ActionView
@template.fields_for(name, object, *args, &block)
else
@template.fields_for(name, object, *args) do |builder|
@template.concat builder.hidden_field(:id)
block.call(builder)
@template.concat builder.hidden_field(:id) unless builder.emitted_hidden_id?
end
end
end

View file

@ -296,7 +296,7 @@ module ActionView
options << %(<option value="#{html_escape(value.to_s)}"#{selected_attribute}#{disabled_attribute}>#{html_escape(text.to_s)}</option>)
end
options_for_select.join("\n")
options_for_select.join("\n").html_safe!
end
# Returns a string of option tags that have been compiled by iterating over the +collection+ and assigning the

View file

@ -432,7 +432,7 @@ module ActionView
concat(tag(:fieldset, options, true))
concat(content_tag(:legend, legend)) unless legend.blank?
concat(content)
concat("</fieldset>")
concat("</fieldset>".html_safe!)
end
private
@ -459,14 +459,14 @@ module ActionView
def form_tag_html(html_options)
extra_tags = extra_tags_for_form(html_options)
tag(:form, html_options, true) + extra_tags
(tag(:form, html_options, true) + extra_tags).html_safe!
end
def form_tag_in_block(html_options, &block)
content = capture(&block)
concat(form_tag_html(html_options))
concat(content)
concat("</form>")
concat("</form>".html_safe!)
end
def token_tag

View file

@ -246,6 +246,11 @@ module ActionView
# number_to_human_size(483989, :precision => 0) # => 473 KB
# number_to_human_size(1234567, :precision => 2, :separator => ',') # => 1,18 MB
#
# Zeros after the decimal point are always stripped out, regardless of the
# specified precision:
# helper.number_to_human_size(1234567890123, :precision => 5) # => "1.12283 TB"
# helper.number_to_human_size(524288000, :precision=>5) # => "500 MB"
#
# You can still use <tt>number_to_human_size</tt> with the old API that accepts the
# +precision+ as its optional second parameter:
# number_to_human_size(1234567, 2) # => 1.18 MB
@ -291,7 +296,7 @@ module ActionView
:precision => precision,
:separator => separator,
:delimiter => delimiter
).sub(/(\d)(#{escaped_separator}[1-9]*)?0+\z/, '\1\2').sub(/#{escaped_separator}\z/, '')
).sub(/(#{escaped_separator})(\d*[1-9])?0+\z/, '\1\2').sub(/#{escaped_separator}\z/, '')
storage_units_format.gsub(/%n/, formatted_number).gsub(/%u/, unit)
rescue
number

View file

@ -393,7 +393,7 @@ module ActionView
concat(form_remote_tag(options))
fields_for(object_name, *(args << options), &proc)
concat('</form>')
concat('</form>'.html_safe!)
end
alias_method :form_remote_for, :remote_form_for

View file

@ -0,0 +1,9 @@
module ActionView #:nodoc:
module Helpers #:nodoc:
module RawOutputHelper
def raw(stringish)
stringish.to_s.html_safe!
end
end
end
end

View file

@ -49,7 +49,11 @@ module ActionView
# confuse browsers.
#
def sanitize(html, options = {})
self.class.white_list_sanitizer.sanitize(html, options)
returning self.class.white_list_sanitizer.sanitize(html, options) do |sanitized|
if sanitized
sanitized.html_safe!
end
end
end
# Sanitizes a block of CSS code. Used by +sanitize+ when it comes across a style attribute.
@ -72,7 +76,11 @@ module ActionView
# strip_tags("<div id='top-bar'>Welcome to my website!</div>")
# # => Welcome to my website!
def strip_tags(html)
self.class.full_sanitizer.sanitize(html)
returning self.class.full_sanitizer.sanitize(html) do |sanitized|
if sanitized
sanitized.html_safe!
end
end
end
# Strips all link tags from +text+ leaving just the link text.

View file

@ -38,7 +38,7 @@ module ActionView
# tag("img", { :src => "open &amp; shut.png" }, false, false)
# # => <img src="open &amp; shut.png" />
def tag(name, options = nil, open = false, escape = true)
"<#{name}#{tag_options(options, escape) if options}#{open ? ">" : " />"}"
"<#{name}#{tag_options(options, escape) if options}#{open ? ">" : " />"}".html_safe!
end
# Returns an HTML block tag of type +name+ surrounding the +content+. Add
@ -91,7 +91,7 @@ module ActionView
# cdata_section(File.read("hello_world.txt"))
# # => <![CDATA[<hello from a text file]]>
def cdata_section(content)
"<![CDATA[#{content}]]>"
"<![CDATA[#{content}]]>".html_safe!
end
# Returns an escaped version of +html+ without affecting existing escaped entities.
@ -125,7 +125,7 @@ module ActionView
def content_tag_string(name, content, options, escape = true)
tag_options = tag_options(options, escape) if options
"<#{name}#{tag_options}>#{content}</#{name}>"
"<#{name}#{tag_options}>#{content}</#{name}>".html_safe!
end
def tag_options(options, escape = true)
@ -142,7 +142,7 @@ module ActionView
else
attrs = options.map { |key, value| %(#{key}="#{value}") }
end
" #{attrs.sort * ' '}" unless attrs.empty?
" #{attrs.sort * ' '}".html_safe! unless attrs.empty?
end
end
end

View file

@ -21,7 +21,7 @@ module ActionView
# Delegates to I18n.localize with no additional functionality.
def localize(*args)
I18n.localize *args
I18n.localize(*args)
end
alias :l :localize

View file

@ -219,7 +219,7 @@ module ActionView
if block_given?
options = args.first || {}
html_options = args.second
concat(link_to(capture(&block), options, html_options))
concat(link_to(capture(&block), options, html_options).html_safe!)
else
name = args.first
options = args.second || {}
@ -237,7 +237,7 @@ module ActionView
end
href_attr = "href=\"#{url}\"" unless href
"<a #{href_attr}#{tag_options}>#{name || url}</a>"
"<a #{href_attr}#{tag_options}>#{name || url}</a>".html_safe!
end
end
@ -309,7 +309,7 @@ module ActionView
html_options.merge!("type" => "submit", "value" => name)
"<form method=\"#{form_method}\" action=\"#{escape_once url}\" class=\"button-to\"><div>" +
method_tag + tag("input", html_options) + request_token_tag + "</div></form>"
method_tag + tag("input", html_options) + request_token_tag + "</div></form>".html_safe!
end

View file

@ -91,6 +91,9 @@
over_x_years:
one: "over 1 year"
other: "over {{count}} years"
almost_x_years:
one: "almost 1 year"
other: "almost {{count}} years"
prompts:
year: "Year"
month: "Month"

View file

@ -221,7 +221,7 @@ module ActionView
result = template.render_partial(self, object, local_assigns.dup, as)
index += 1
result
end.join(spacer)
end.join(spacer).html_safe!
end
def _pick_partial_template(partial_path) #:nodoc:

View file

@ -0,0 +1,28 @@
module ActionView #:nodoc:
class SafeBuffer < String
def <<(value)
if value.html_safe?
super(value)
else
super(ERB::Util.h(value))
end
end
def concat(value)
self << value
end
def html_safe?
true
end
def html_safe!
self
end
def to_s
self
end
end
end

View file

@ -57,9 +57,14 @@ module ActionView #:nodoc:
end
class EagerPath < Path
def initialize(path)
super
@loaded = false
end
def load!
return if @loaded
@paths = {}
templates_in_path do |template|
template.load!
@ -103,8 +108,9 @@ module ActionView #:nodoc:
@@exempt_from_layout.merge(regexps)
end
attr_accessor :template_path, :filename, :load_path, :base_path
attr_accessor :template_path, :load_path, :base_path
attr_accessor :locale, :name, :format, :extension
attr_writer :filename
delegate :to_s, :to => :path
def initialize(template_path, load_path = nil)

View file

@ -22,11 +22,52 @@ module ActionView
end
class TestCase < ActiveSupport::TestCase
class TestController < ActionController::Base
attr_accessor :request, :response, :params
def self.controller_path
''
end
def initialize
@request = ActionController::TestRequest.new
@response = ActionController::TestResponse.new
@params = {}
send(:initialize_current_url)
end
end
include ActionController::TestCase::Assertions
include ActionController::TestProcess
include ActionController::PolymorphicRoutes
include ActionController::RecordIdentifier
include ActionView::Helpers
include ActionController::Helpers
class_inheritable_accessor :helper_class
@@helper_class = nil
attr_accessor :controller, :output_buffer, :rendered
setup :setup_with_controller
def setup_with_controller
@controller = TestController.new
@output_buffer = ''
@rendered = ''
self.class.send(:include_helper_modules!)
make_test_case_available_to_view!
end
def render(options = {}, local_assigns = {}, &block)
@rendered << output = _view.render(options, local_assigns, &block)
output
end
def protect_against_forgery?
false
end
class << self
def tests(helper_class)
@ -46,42 +87,76 @@ module ActionView
rescue NameError
nil
end
end
include ActionView::Helpers
include ActionController::PolymorphicRoutes
include ActionController::RecordIdentifier
setup :setup_with_helper_class
def setup_with_helper_class
if helper_class && !self.class.ancestors.include?(helper_class)
self.class.send(:include, helper_class)
def helper_method(*methods)
# Almost a duplicate from ActionController::Helpers
methods.flatten.each do |method|
master_helper_module.module_eval <<-end_eval
def #{method}(*args, &block) # def current_user(*args, &block)
_test_case.send(%(#{method}), *args, &block) # test_case.send(%(current_user), *args, &block)
end # end
end_eval
end
end
self.output_buffer = ''
private
def include_helper_modules!
helper(helper_class) if helper_class
include master_helper_module
end
end
class TestController < ActionController::Base
attr_accessor :request, :response, :params
def initialize
@request = ActionController::TestRequest.new
@response = ActionController::TestResponse.new
@params = {}
send(:initialize_current_url)
end
end
protected
attr_accessor :output_buffer
private
def make_test_case_available_to_view!
test_case_instance = self
master_helper_module.module_eval do
define_method(:_test_case) { test_case_instance }
private :_test_case
end
end
def _view
view = ActionView::Base.new(ActionController::Base.view_paths, _assigns, @controller)
view.helpers.include master_helper_module
view.output_buffer = self.output_buffer
view
end
# Support the selector assertions
#
# Need to experiment if this priority is the best one: rendered => output_buffer
def response_from_page_or_rjs
HTML::Document.new(rendered.blank? ? output_buffer : rendered).root
end
EXCLUDE_IVARS = %w{
@output_buffer
@fixture_cache
@method_name
@_result
@loaded_fixtures
@test_passed
@view
}
def _instance_variables
instance_variables - EXCLUDE_IVARS
end
def _assigns
_instance_variables.inject({}) do |hash, var|
name = var[1..-1].to_sym
hash[name] = instance_variable_get(var)
hash
end
end
def method_missing(selector, *args)
controller = TestController.new
return controller.__send__(selector, *args) if ActionController::Routing::Routes.named_routes.helpers.include?(selector)
super
if ActionController::Routing::Routes.named_routes.helpers.include?(selector)
@controller.__send__(selector, *args)
else
super
end
end
end
end
end

View file

@ -1 +1,2 @@
require 'action_pack'
ActiveSupport::Deprecation.warn 'require "actionpack" is deprecated and will be removed in Rails 3. Use require "action_pack" instead.'

View file

@ -114,6 +114,13 @@ class CookieTest < ActionController::TestCase
assert_equal %w{1 2 3}, jar["pages"]
end
def test_cookiejar_delete_removes_item_and_returns_its_value
@request.cookies["user_name"] = "david"
@controller.response = @response
jar = ActionController::CookieJar.new(@controller)
assert_equal "david", jar.delete("user_name")
end
def test_delete_cookie_with_path
get :delete_cookie_with_path
assert_equal ["user_name=; path=/beaten; expires=Thu, 01-Jan-1970 00:00:00 GMT"], @response.headers["Set-Cookie"]

View file

@ -0,0 +1,53 @@
require 'abstract_unit'
class DomAssertionsTest < ActionView::TestCase
def setup
super
@html_only = '<ul><li>foo</li><li>bar</li></ul>'
@html_with_meaningless_whitespace = %{
<ul>
<li>\tfoo </li>
<li>
bar
</li>
</ul>
}
@more_html_with_meaningless_whitespace = %{<ul>
<li>foo</li>
<li>bar</li></ul>}
end
test "assert_dom_equal strips meaningless whitespace from expected string" do
assert_dom_equal @html_with_meaningless_whitespace, @html_only
end
test "assert_dom_equal strips meaningless whitespace from actual string" do
assert_dom_equal @html_only, @html_with_meaningless_whitespace
end
test "assert_dom_equal strips meaningless whitespace from both expected and actual strings" do
assert_dom_equal @more_html_with_meaningless_whitespace, @html_with_meaningless_whitespace
end
test "assert_dom_not_equal strips meaningless whitespace from expected string" do
assert_assertion_fails { assert_dom_not_equal @html_with_meaningless_whitespace, @html_only }
end
test "assert_dom_not_equal strips meaningless whitespace from actual string" do
assert_assertion_fails { assert_dom_not_equal @html_only, @html_with_meaningless_whitespace }
end
test "assert_dom_not_equal strips meaningless whitespace from both expected and actual strings" do
assert_assertion_fails do
assert_dom_not_equal @more_html_with_meaningless_whitespace, @html_with_meaningless_whitespace
end
end
private
def assert_assertion_fails
assert_raise(ActiveSupport::TestCase::Assertion) { yield }
end
end

View file

@ -18,6 +18,7 @@ class FilterParamTest < Test::Unit::TestCase
test_hashes = [[{},{},[]],
[{'foo'=>nil},{'foo'=>nil},[]],
[{'foo'=>'bar'},{'foo'=>'bar'},[]],
[{'foo'=>1},{'foo'=>1},[]],
[{'foo'=>'bar'},{'foo'=>'bar'},%w'food'],
[{'foo'=>'bar'},{'foo'=>'[FILTERED]'},%w'foo'],
[{'foo'=>'bar', 'bar'=>'foo'},{'foo'=>'[FILTERED]', 'bar'=>'foo'},%w'foo baz'],

View file

@ -19,6 +19,7 @@ class SanitizerTest < ActionController::TestCase
assert_equal "This has a here.", sanitizer.sanitize("This has a <!-- comment --> here.")
assert_equal "This has a here.", sanitizer.sanitize("This has a <![CDATA[<section>]]> here.")
assert_equal "This has an unclosed ", sanitizer.sanitize("This has an unclosed <![CDATA[<section>]] here...")
assert_equal "non printable char is a tag", sanitizer.sanitize("<\x07a href='/hello'>non printable char is a tag</a>")
[nil, '', ' '].each { |blank| assert_equal blank, sanitizer.sanitize(blank) }
end

View file

@ -92,6 +92,23 @@ class HttpDigestAuthenticationTest < ActionController::TestCase
assert_equal "Authentication Failed", @response.body
end
test "authentication request with missing nonce should return 401" do
@request.env['HTTP_AUTHORIZATION'] = encode_credentials(:username => 'pretty', :password => 'please', :remove_nonce => true)
get :display
assert_response :unauthorized
assert_equal "Authentication Failed", @response.body
end
test "authentication request with Basic auth credentials should return 401" do
ActionController::Base.session_options[:secret] = "session_options_secret"
@request.env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Basic.encode_credentials('pretty', 'please')
get :display
assert_response :unauthorized
assert_equal "Authentication Failed", @response.body
end
test "authentication request with invalid opaque" do
@request.env['HTTP_AUTHORIZATION'] = encode_credentials(:username => 'pretty', :password => 'foo', :opaque => "xxyyzz")
get :display
@ -220,9 +237,14 @@ class HttpDigestAuthenticationTest < ActionController::TestCase
assert_response :unauthorized
remove_nonce = options.delete(:remove_nonce)
credentials = decode_credentials(@response.headers['WWW-Authenticate'])
credentials.merge!(options)
credentials.merge!(:uri => @request.env['REQUEST_URI'].to_s)
credentials.delete(:nonce) if remove_nonce
ActionController::HttpAuthentication::Digest.encode_credentials(method, credentials, password, options[:password_is_ha1])
end

View file

@ -207,6 +207,24 @@ class IntegrationTestTest < Test::Unit::TestCase
assert_equal ::ActionController::Integration::Session, session2.class
assert_not_equal session1, session2
end
# RSpec mixes Matchers (which has a #method_missing) into
# IntegrationTest's superclass. Make sure IntegrationTest does not
# try to delegate these methods to the session object.
def test_does_not_prevent_method_missing_passing_up_to_ancestors
mixin = Module.new do
def method_missing(name, *args)
name.to_s == 'foo' ? 'pass' : super
end
end
@test.class.superclass.__send__(:include, mixin)
begin
assert_equal 'pass', @test.foo
ensure
# leave other tests as unaffected as possible
mixin.__send__(:remove_method, :method_missing)
end
end
end
# Tests that integration tests don't call Controller test methods for processing.
@ -443,3 +461,23 @@ class MetalTest < ActionController::IntegrationTest
assert_equal '', response.body
end
end
class StringSubclassBodyTest < ActionController::IntegrationTest
class SafeString < String
end
class SafeStringMiddleware
def self.call(env)
[200, {"Content-Type" => "text/plain", "Content-Length" => "12"}, [SafeString.new("Hello World!")]]
end
end
def setup
@integration_session = ActionController::Integration::Session.new(SafeStringMiddleware)
end
def test_string_subclass_body
get '/'
assert_equal 'Hello World!', response.body
end
end

View file

@ -83,6 +83,11 @@ class AbsolutePathLayoutController < LayoutTest
layout File.expand_path(File.expand_path(__FILE__) + '/../../fixtures/layout_tests/layouts/layout_test.rhtml')
end
class AbsolutePathWithoutLayoutsController < LayoutTest
# Absolute layout path without 'layouts' in it.
layout File.expand_path(File.expand_path(__FILE__) + '/../../fixtures/layout_tests/abs_path_layout.rhtml')
end
class HasOwnLayoutController < LayoutTest
layout 'item'
end
@ -153,6 +158,12 @@ class LayoutSetInResponseTest < ActionController::TestCase
get :hello
assert_equal "layout_test.rhtml hello.rhtml", @response.body.strip
end
def test_absolute_pathed_layout_without_layouts_in_path
@controller = AbsolutePathWithoutLayoutsController.new
get :hello
assert_equal "abs_path_layout.rhtml hello.rhtml", @response.body.strip
end
end
class RenderWithTemplateOptionController < LayoutTest

View file

@ -290,4 +290,8 @@ class PolymorphicRoutesTest < ActiveSupport::TestCase
polymorphic_url([:taxes])
end
def test_with_array_containing_symbols
expects(:new_article_url).with()
polymorphic_url([:new, :article])
end
end

View file

@ -22,7 +22,7 @@ module RequestForgeryProtectionActions
def unsafe
render :text => 'pwn'
end
def rescue_action(e) raise e end
end
@ -44,6 +44,13 @@ class FreeCookieController < RequestForgeryProtectionController
end
end
class CustomAuthenticityParamController < RequestForgeryProtectionController
def form_authenticity_param
'foobar'
end
end
# common test methods
module RequestForgeryProtectionTests
@ -245,3 +252,14 @@ class FreeCookieControllerTest < ActionController::TestCase
end
end
end
class CustomAuthenticityParamControllerTest < ActionController::TestCase
def setup
ActionController::Base.request_forgery_protection_token = :authenticity_token
end
def test_should_allow_custom_token
post :index, :authenticity_token => 'foobar'
assert_response :ok
end
end

View file

@ -107,7 +107,11 @@ class StaticSegmentTest < Test::Unit::TestCase
end
end
class DynamicSegmentTest < Test::Unit::TestCase
class DynamicSegmentTest < ActiveSupport::TestCase
def setup
@segment = nil
end
def segment(options = {})
unless @segment
@segment = ROUTING::DynamicSegment.new(:a, options)
@ -341,7 +345,11 @@ class ControllerSegmentTest < Test::Unit::TestCase
end
end
class PathSegmentTest < Test::Unit::TestCase
class PathSegmentTest < ActiveSupport::TestCase
def setup
@segment = nil
end
def segment(options = {})
unless @segment
@segment = ROUTING::PathSegment.new(:path, options)
@ -754,7 +762,7 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
ActionController::Routing.use_controllers! %w(content admin/user admin/news_feed)
end
def teardown
@rs.clear!
end
@ -1094,21 +1102,21 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
map.post 'post/:id', :controller=> 'post', :action=> 'show', :requirements => {:id => /\d+/}
end
exception = assert_raise(ActionController::RoutingError) { rs.generate(:controller => 'post', :action => 'show', :bad_param => "foo", :use_route => "post") }
assert_match /^post_url failed to generate/, exception.message
assert_match(/^post_url failed to generate/, exception.message)
from_match = exception.message.match(/from \{[^\}]+\}/).to_s
assert_match /:bad_param=>"foo"/, from_match
assert_match /:action=>"show"/, from_match
assert_match /:controller=>"post"/, from_match
assert_match(/:bad_param=>"foo"/, from_match)
assert_match(/:action=>"show"/, from_match)
assert_match(/:controller=>"post"/, from_match)
expected_match = exception.message.match(/expected: \{[^\}]+\}/).to_s
assert_no_match /:bad_param=>"foo"/, expected_match
assert_match /:action=>"show"/, expected_match
assert_match /:controller=>"post"/, expected_match
assert_no_match(/:bad_param=>"foo"/, expected_match)
assert_match( /:action=>"show"/, expected_match)
assert_match( /:controller=>"post"/, expected_match)
diff_match = exception.message.match(/diff: \{[^\}]+\}/).to_s
assert_match /:bad_param=>"foo"/, diff_match
assert_no_match /:action=>"show"/, diff_match
assert_no_match /:controller=>"post"/, diff_match
assert_match( /:bad_param=>"foo"/, diff_match)
assert_no_match(/:action=>"show"/, diff_match)
assert_no_match(/:controller=>"post"/, diff_match)
end
# this specifies the case where your formerly would get a very confusing error message with an empty diff
@ -2564,10 +2572,10 @@ class RouteLoadingTest < Test::Unit::TestCase
routes.reload
end
def test_load_multiple_configurations
routes.add_configuration_file("engines.rb")
File.expects(:stat).at_least_once.returns(@stat)
routes.expects(:load).with('./config/routes.rb')

View file

@ -33,11 +33,11 @@ class ActionController::TestSessionTest < ActiveSupport::TestCase
assert_equal('value', session[:key])
end
def test_calling_delete_removes_item
def test_calling_delete_removes_item_and_returns_its_value
session = ActionController::TestSession.new
session[:key] = 'value'
assert_equal('value', session[:key])
session.delete(:key)
assert_equal('value', session.delete(:key))
assert_nil(session[:key])
end

View file

@ -0,0 +1 @@
abs_path_layout.rhtml <%= yield %>

View file

@ -0,0 +1 @@
<%= render_from_helper %>

View file

@ -183,7 +183,7 @@ class ActiveRecordHelperTest < ActionView::TestCase
end
def test_form_with_action_option
@response.body = form("post", :action => "sign")
output_buffer << form("post", :action => "sign")
assert_select "form[action=sign]" do |form|
assert_select "input[type=submit][value=Sign]"
end

View file

@ -164,6 +164,11 @@ class AssetTagHelperTest < ActionView::TestCase
assert_dom_equal(%(<script src="/javascripts/prototype.js?1" type="text/javascript"></script>\n<script src="/javascripts/effects.js?1" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js?1" type="text/javascript"></script>\n<script src="/javascripts/controls.js?1" type="text/javascript"></script>\n<script src="/javascripts/application.js?1" type="text/javascript"></script>), javascript_include_tag(:defaults))
end
def test_javascript_include_tag_is_html_safe
assert javascript_include_tag(:defaults).html_safe?
assert javascript_include_tag("prototype").html_safe?
end
def test_register_javascript_include_default
ENV["RAILS_ASSET_ID"] = ""
ActionView::Helpers::AssetTagHelper::register_javascript_include_default 'slider'
@ -206,6 +211,13 @@ class AssetTagHelperTest < ActionView::TestCase
StyleLinkToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) }
end
def test_stylesheet_link_tag_is_html_safe
ENV["RAILS_ASSET_ID"] = ""
assert stylesheet_link_tag('dir/file').html_safe?
assert stylesheet_link_tag('dir/other/file', 'dir/file2').html_safe?
assert stylesheet_tag('dir/file', {}).html_safe?
end
def test_custom_stylesheet_expansions
ActionView::Helpers::AssetTagHelper::register_stylesheet_expansion :monkey => ["head", "body", "tail"]
assert_dom_equal %(<link href="/stylesheets/first.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/head.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/body.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/tail.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/last.css" media="screen" rel="stylesheet" type="text/css" />), stylesheet_link_tag('first', :monkey, 'last')

View file

@ -4,14 +4,14 @@ require 'action_view/helpers/benchmark_helper'
class BenchmarkHelperTest < ActionView::TestCase
tests ActionView::Helpers::BenchmarkHelper
def teardown
controller.logger.send(:clear_buffer)
def setup
super
controller.logger = ActiveSupport::BufferedLogger.new(StringIO.new)
controller.logger.auto_flushing = false
end
def controller
logger = ActiveSupport::BufferedLogger.new(StringIO.new)
logger.auto_flushing = false
@controller ||= Struct.new(:logger).new(logger)
def teardown
controller.logger.send(:clear_buffer)
end
def test_without_block

View file

@ -2,8 +2,9 @@ require 'abstract_unit'
require 'controller/fake_models'
class CompiledTemplatesTest < Test::Unit::TestCase
def setup
@explicit_view_paths = nil
@compiled_templates = ActionView::Base::CompiledTemplates
@compiled_templates.instance_methods.each do |m|
@compiled_templates.send(:remove_method, m) if m =~ /^_run_/

View file

@ -20,15 +20,16 @@ class DateHelperDistanceOfTimeInWordsI18nTests < Test::Unit::TestCase
[60.seconds, true] => [:'x_minutes', 1],
# without include_seconds
[29.seconds, false] => [:'less_than_x_minutes', 1],
[60.seconds, false] => [:'x_minutes', 1],
[44.minutes, false] => [:'x_minutes', 44],
[61.minutes, false] => [:'about_x_hours', 1],
[24.hours, false] => [:'x_days', 1],
[30.days, false] => [:'about_x_months', 1],
[60.days, false] => [:'x_months', 2],
[1.year, false] => [:'about_x_years', 1],
[3.years, false] => [:'over_x_years', 3]
[29.seconds, false] => [:'less_than_x_minutes', 1],
[60.seconds, false] => [:'x_minutes', 1],
[44.minutes, false] => [:'x_minutes', 44],
[61.minutes, false] => [:'about_x_hours', 1],
[24.hours, false] => [:'x_days', 1],
[30.days, false] => [:'about_x_months', 1],
[60.days, false] => [:'x_months', 2],
[1.year, false] => [:'about_x_years', 1],
[3.years + 6.months, false] => [:'over_x_years', 3],
[3.years + 10.months, false] => [:'almost_x_years', 4]
}.each do |passed, expected|
assert_distance_of_time_in_words_translates_key passed, expected

View file

@ -53,13 +53,14 @@ class DateHelperTest < ActionView::TestCase
assert_equal "about 2 hours", distance_of_time_in_words(from, to + 89.minutes + 30.seconds)
assert_equal "about 24 hours", distance_of_time_in_words(from, to + 23.hours + 59.minutes + 29.seconds)
# 1440..2879
# 1440..2529
assert_equal "1 day", distance_of_time_in_words(from, to + 23.hours + 59.minutes + 30.seconds)
assert_equal "1 day", distance_of_time_in_words(from, to + 47.hours + 59.minutes + 29.seconds)
assert_equal "1 day", distance_of_time_in_words(from, to + 41.hours + 59.minutes + 29.seconds)
# 2880..43199
assert_equal "2 days", distance_of_time_in_words(from, to + 47.hours + 59.minutes + 30.seconds)
assert_equal "29 days", distance_of_time_in_words(from, to + 29.days + 23.hours + 59.minutes + 29.seconds)
# 2530..43199
assert_equal "2 days", distance_of_time_in_words(from, to + 42.hours + 59.minutes + 30.seconds)
assert_equal "3 days", distance_of_time_in_words(from, to + 2.days + 12.hours)
assert_equal "30 days", distance_of_time_in_words(from, to + 29.days + 23.hours + 59.minutes + 29.seconds)
# 43200..86399
assert_equal "about 1 month", distance_of_time_in_words(from, to + 29.days + 23.hours + 59.minutes + 30.seconds)
@ -69,13 +70,28 @@ class DateHelperTest < ActionView::TestCase
assert_equal "2 months", distance_of_time_in_words(from, to + 59.days + 23.hours + 59.minutes + 30.seconds)
assert_equal "12 months", distance_of_time_in_words(from, to + 1.years - 31.seconds)
# 525600..1051199
assert_equal "about 1 year", distance_of_time_in_words(from, to + 1.years - 30.seconds)
assert_equal "about 1 year", distance_of_time_in_words(from, to + 2.years - 31.seconds)
# > 525599
assert_equal "about 1 year", distance_of_time_in_words(from, to + 1.years - 30.seconds)
assert_equal "about 1 year", distance_of_time_in_words(from, to + 1.years + 3.months - 1.day)
assert_equal "over 1 year", distance_of_time_in_words(from, to + 1.years + 6.months)
# > 1051199
assert_equal "over 2 years", distance_of_time_in_words(from, to + 2.years + 30.seconds)
assert_equal "over 10 years", distance_of_time_in_words(from, to + 10.years)
assert_equal "almost 2 years", distance_of_time_in_words(from, to + 2.years - 3.months + 1.day)
assert_equal "about 2 years", distance_of_time_in_words(from, to + 2.years + 3.months - 1.day)
assert_equal "over 2 years", distance_of_time_in_words(from, to + 2.years + 3.months + 1.day)
assert_equal "over 2 years", distance_of_time_in_words(from, to + 2.years + 9.months - 1.day)
assert_equal "almost 3 years", distance_of_time_in_words(from, to + 2.years + 9.months + 1.day)
assert_equal "almost 5 years", distance_of_time_in_words(from, to + 5.years - 3.months + 1.day)
assert_equal "about 5 years", distance_of_time_in_words(from, to + 5.years + 3.months - 1.day)
assert_equal "over 5 years", distance_of_time_in_words(from, to + 5.years + 3.months + 1.day)
assert_equal "over 5 years", distance_of_time_in_words(from, to + 5.years + 9.months - 1.day)
assert_equal "almost 6 years", distance_of_time_in_words(from, to + 5.years + 9.months + 1.day)
assert_equal "almost 10 years", distance_of_time_in_words(from, to + 10.years - 3.months + 1.day)
assert_equal "about 10 years", distance_of_time_in_words(from, to + 10.years + 3.months - 1.day)
assert_equal "over 10 years", distance_of_time_in_words(from, to + 10.years + 3.months + 1.day)
assert_equal "over 10 years", distance_of_time_in_words(from, to + 10.years + 9.months - 1.day)
assert_equal "almost 11 years", distance_of_time_in_words(from, to + 10.years + 9.months + 1.day)
# test to < from
assert_equal "about 4 hours", distance_of_time_in_words(from + 4.hours, to)
@ -104,7 +120,7 @@ class DateHelperTest < ActionView::TestCase
def test_distance_in_words_with_dates
start_date = Date.new 1975, 1, 31
end_date = Date.new 1977, 1, 31
assert_equal("over 2 years", distance_of_time_in_words(start_date, end_date))
assert_equal("about 2 years", distance_of_time_in_words(start_date, end_date))
end
def test_distance_in_words_with_integers

View file

@ -697,6 +697,26 @@ class FormHelperTest < ActionView::TestCase
end
end
expected = '<form action="http://www.example.com" method="post">' +
'<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' +
'<input id="post_author_attributes_name" name="post[author_attributes][name]" size="30" type="text" value="author #321" />' +
'<input id="post_author_attributes_id" name="post[author_attributes][id]" type="hidden" value="321" />' +
'</form>'
assert_dom_equal expected, output_buffer
end
def test_nested_fields_for_with_existing_records_on_a_nested_attributes_one_to_one_association_with_explicit_hidden_field_placement
@post.author = Author.new(321)
form_for(:post, @post) do |f|
concat f.text_field(:title)
f.fields_for(:author) do |af|
concat af.hidden_field(:id)
concat af.text_field(:name)
end
end
expected = '<form action="http://www.example.com" method="post">' +
'<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' +
'<input id="post_author_attributes_id" name="post[author_attributes][id]" type="hidden" value="321" />' +
@ -718,6 +738,30 @@ class FormHelperTest < ActionView::TestCase
end
end
expected = '<form action="http://www.example.com" method="post">' +
'<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' +
'<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="comment #1" />' +
'<input id="post_comments_attributes_0_id" name="post[comments_attributes][0][id]" type="hidden" value="1" />' +
'<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" size="30" type="text" value="comment #2" />' +
'<input id="post_comments_attributes_1_id" name="post[comments_attributes][1][id]" type="hidden" value="2" />' +
'</form>'
assert_dom_equal expected, output_buffer
end
def test_nested_fields_for_with_existing_records_on_a_nested_attributes_collection_association_with_explicit_hidden_field_placement
@post.comments = Array.new(2) { |id| Comment.new(id + 1) }
form_for(:post, @post) do |f|
concat f.text_field(:title)
@post.comments.each do |comment|
f.fields_for(:comments, comment) do |cf|
concat cf.hidden_field(:id)
concat cf.text_field(:name)
end
end
end
expected = '<form action="http://www.example.com" method="post">' +
'<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' +
'<input id="post_comments_attributes_0_id" name="post[comments_attributes][0][id]" type="hidden" value="1" />' +
@ -764,14 +808,50 @@ class FormHelperTest < ActionView::TestCase
expected = '<form action="http://www.example.com" method="post">' +
'<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' +
'<input id="post_comments_attributes_0_id" name="post[comments_attributes][0][id]" type="hidden" value="321" />' +
'<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="comment #321" />' +
'<input id="post_comments_attributes_0_id" name="post[comments_attributes][0][id]" type="hidden" value="321" />' +
'<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" size="30" type="text" value="new comment" />' +
'</form>'
assert_dom_equal expected, output_buffer
end
def test_nested_fields_for_with_an_empty_supplied_attributes_collection
form_for(:post, @post) do |f|
concat f.text_field(:title)
f.fields_for(:comments, []) do |cf|
concat cf.text_field(:name)
end
end
expected = '<form action="http://www.example.com" method="post">' +
'<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' +
'</form>'
assert_dom_equal expected, output_buffer
end
def test_nested_fields_for_with_existing_records_on_a_supplied_nested_attributes_collection
@post.comments = Array.new(2) { |id| Comment.new(id + 1) }
form_for(:post, @post) do |f|
concat f.text_field(:title)
f.fields_for(:comments, @post.comments) do |cf|
concat cf.text_field(:name)
end
end
expected = '<form action="http://www.example.com" method="post">' +
'<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' +
'<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="comment #1" />' +
'<input id="post_comments_attributes_0_id" name="post[comments_attributes][0][id]" type="hidden" value="1" />' +
'<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" size="30" type="text" value="comment #2" />' +
'<input id="post_comments_attributes_1_id" name="post[comments_attributes][1][id]" type="hidden" value="2" />' +
'</form>'
assert_dom_equal expected, output_buffer
end
def test_nested_fields_for_on_a_nested_attributes_collection_association_yields_only_builder
@post.comments = [Comment.new(321), Comment.new]
yielded_comments = []
@ -786,8 +866,8 @@ class FormHelperTest < ActionView::TestCase
expected = '<form action="http://www.example.com" method="post">' +
'<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' +
'<input id="post_comments_attributes_0_id" name="post[comments_attributes][0][id]" type="hidden" value="321" />' +
'<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="comment #321" />' +
'<input id="post_comments_attributes_0_id" name="post[comments_attributes][0][id]" type="hidden" value="321" />' +
'<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" size="30" type="text" value="new comment" />' +
'</form>'
@ -805,8 +885,8 @@ class FormHelperTest < ActionView::TestCase
end
expected = '<form action="http://www.example.com" method="post">' +
'<input id="post_comments_attributes_abc_id" name="post[comments_attributes][abc][id]" type="hidden" value="321" />' +
'<input id="post_comments_attributes_abc_name" name="post[comments_attributes][abc][name]" size="30" type="text" value="comment #321" />' +
'<input id="post_comments_attributes_abc_id" name="post[comments_attributes][abc][id]" type="hidden" value="321" />' +
'</form>'
assert_dom_equal expected, output_buffer
@ -840,18 +920,18 @@ class FormHelperTest < ActionView::TestCase
end
expected = '<form action="http://www.example.com" method="post">' +
'<input id="post_comments_attributes_0_id" name="post[comments_attributes][0][id]" type="hidden" value="321" />' +
'<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="comment #321" />' +
'<input id="post_comments_attributes_0_relevances_attributes_0_id" name="post[comments_attributes][0][relevances_attributes][0][id]" type="hidden" value="314" />' +
'<input id="post_comments_attributes_0_relevances_attributes_0_value" name="post[comments_attributes][0][relevances_attributes][0][value]" size="30" type="text" value="commentrelevance #314" />' +
'<input id="post_tags_attributes_0_id" name="post[tags_attributes][0][id]" type="hidden" value="123" />' +
'<input id="post_comments_attributes_0_relevances_attributes_0_id" name="post[comments_attributes][0][relevances_attributes][0][id]" type="hidden" value="314" />' +
'<input id="post_comments_attributes_0_id" name="post[comments_attributes][0][id]" type="hidden" value="321" />' +
'<input id="post_tags_attributes_0_value" name="post[tags_attributes][0][value]" size="30" type="text" value="tag #123" />' +
'<input id="post_tags_attributes_0_relevances_attributes_0_id" name="post[tags_attributes][0][relevances_attributes][0][id]" type="hidden" value="3141" />' +
'<input id="post_tags_attributes_0_relevances_attributes_0_value" name="post[tags_attributes][0][relevances_attributes][0][value]" size="30" type="text" value="tagrelevance #3141" />' +
'<input id="post_tags_attributes_1_id" name="post[tags_attributes][1][id]" type="hidden" value="456" />' +
'<input id="post_tags_attributes_0_relevances_attributes_0_id" name="post[tags_attributes][0][relevances_attributes][0][id]" type="hidden" value="3141" />' +
'<input id="post_tags_attributes_0_id" name="post[tags_attributes][0][id]" type="hidden" value="123" />' +
'<input id="post_tags_attributes_1_value" name="post[tags_attributes][1][value]" size="30" type="text" value="tag #456" />' +
'<input id="post_tags_attributes_1_relevances_attributes_0_id" name="post[tags_attributes][1][relevances_attributes][0][id]" type="hidden" value="31415" />' +
'<input id="post_tags_attributes_1_relevances_attributes_0_value" name="post[tags_attributes][1][relevances_attributes][0][value]" size="30" type="text" value="tagrelevance #31415" />' +
'<input id="post_tags_attributes_1_relevances_attributes_0_id" name="post[tags_attributes][1][relevances_attributes][0][id]" type="hidden" value="31415" />' +
'<input id="post_tags_attributes_1_id" name="post[tags_attributes][1][id]" type="hidden" value="456" />' +
'</form>'
assert_dom_equal expected, output_buffer
@ -1024,7 +1104,7 @@ class FormHelperTest < ActionView::TestCase
(field_helpers - %w(hidden_field)).each do |selector|
src = <<-END_SRC
def #{selector}(field, *args, &proc)
"<label for='\#{field}'>\#{field.to_s.humanize}:</label> " + super + "<br/>"
("<label for='\#{field}'>\#{field.to_s.humanize}:</label> " + super + "<br/>").html_safe!
end
END_SRC
class_eval src, __FILE__, __LINE__

View file

@ -118,6 +118,10 @@ class NumberHelperTest < ActionView::TestCase
assert_equal '1.01 KB', number_to_human_size(1.0123.kilobytes, :precision => 2)
assert_equal '1.01 KB', number_to_human_size(1.0100.kilobytes, :precision => 4)
assert_equal '10 KB', number_to_human_size(10.000.kilobytes, :precision => 4)
assert_equal '1 TB', number_to_human_size(1234567890123, :precision => 0)
assert_equal '500 MB', number_to_human_size(524288000, :precision=>0)
assert_equal '40 KB', number_to_human_size(41010, :precision => 0)
assert_equal '40 KB', number_to_human_size(41100, :precision => 0)
end
def test_number_to_human_size_with_custom_delimiter_and_separator

View file

@ -0,0 +1,21 @@
require 'abstract_unit'
require 'testing_sandbox'
class RawOutputHelperTest < ActionView::TestCase
tests ActionView::Helpers::RawOutputHelper
include TestingSandbox
def setup
@string = "hello"
end
test "raw returns the safe string" do
result = raw(@string)
assert_equal @string, result
assert result.html_safe?
end
test "raw handles nil values correctly" do
assert_equal "", raw(nil)
end
end

View file

@ -39,7 +39,16 @@ class SanitizeHelperTest < ActionView::TestCase
%{This is a test.\n\n\nIt no longer contains any HTML.\n}, strip_tags(
%{<title>This is <b>a <a href="" target="_blank">test</a></b>.</title>\n\n<!-- it has a comment -->\n\n<p>It no <b>longer <strong>contains <em>any <strike>HTML</strike></em>.</strong></b></p>\n}))
assert_equal "This has a here.", strip_tags("This has a <!-- comment --> here.")
[nil, '', ' '].each { |blank| assert_equal blank, strip_tags(blank) }
[nil, '', ' '].each do |blank|
stripped = strip_tags(blank)
assert_equal blank, stripped
assert stripped.html_safe? unless blank.nil?
end
assert strip_tags("<script>").html_safe?
end
def test_sanitize_is_marked_safe
assert sanitize("<html><script></script></html>").html_safe?
end
def assert_sanitized(text, expected = nil)

View file

@ -34,6 +34,7 @@ class TagHelperTest < ActionView::TestCase
def test_content_tag
assert_equal "<a href=\"create\">Create</a>", content_tag("a", "Create", "href" => "create")
assert content_tag("a", "Create", "href" => "create").html_safe?
assert_equal content_tag("a", "Create", "href" => "create"),
content_tag("a", "Create", :href => "create")
end

View file

@ -0,0 +1,36 @@
require 'abstract_unit'
class SafeBufferTest < ActionView::TestCase
def setup
@buffer = ActionView::SafeBuffer.new
end
test "Should look like a string" do
assert @buffer.is_a?(String)
assert_equal "", @buffer
end
test "Should escape a raw string which is passed to them" do
@buffer << "<script>"
assert_equal "&lt;script&gt;", @buffer
end
test "Should NOT escape a safe value passed to it" do
@buffer << "<script>".html_safe!
assert_equal "<script>", @buffer
end
test "Should not mess with an innocuous string" do
@buffer << "Hello"
assert_equal "Hello", @buffer
end
test "Should be considered safe" do
assert @buffer.html_safe?
end
test "Should return a safe buffer when calling to_s" do
new_buffer = @buffer.to_s
assert_equal ActionView::SafeBuffer, new_buffer.class
end
end

View file

@ -1,8 +1,176 @@
require 'abstract_unit'
class TestCaseTest < ActionView::TestCase
def test_should_have_current_url
controller = TestController.new
assert_nothing_raised(NoMethodError){ controller.url_for({:controller => "foo", :action => "index"}) }
module ActionView
class TestCase
module ATestHelper
end
module AnotherTestHelper
def from_another_helper
'Howdy!'
end
end
module ASharedTestHelper
def from_shared_helper
'Holla!'
end
end
helper ASharedTestHelper
module SharedTests
def self.included(test_case)
test_case.class_eval do
test "helpers defined on ActionView::TestCase are available" do
assert test_case.ancestors.include?(ASharedTestHelper)
assert_equal 'Holla!', from_shared_helper
end
end
end
end
class GeneralViewTest < ActionView::TestCase
include SharedTests
test_case = self
test "works without testing a helper module" do
assert_equal 'Eloy', render('developers/developer', :developer => stub(:name => 'Eloy'))
end
test "can render a layout with block" do
assert_equal "Before (ChrisCruft)\n!\nAfter",
render(:layout => "test/layout_for_partial", :locals => {:name => "ChrisCruft"}) {"!"}
end
helper AnotherTestHelper
test "additional helper classes can be specified as in a controller" do
assert test_case.ancestors.include?(AnotherTestHelper)
assert_equal 'Howdy!', from_another_helper
end
end
class ClassMethodsTest < ActionView::TestCase
include SharedTests
test_case = self
tests ATestHelper
test "tests the specified helper module" do
assert_equal ATestHelper, test_case.helper_class
assert test_case.ancestors.include?(ATestHelper)
end
helper AnotherTestHelper
test "additional helper classes can be specified as in a controller" do
assert test_case.ancestors.include?(AnotherTestHelper)
assert_equal 'Howdy!', from_another_helper
test_case.helper_class.module_eval do
def render_from_helper
from_another_helper
end
end
assert_equal 'Howdy!', render(:partial => 'test/from_helper')
end
end
class ATestHelperTest < ActionView::TestCase
include SharedTests
test_case = self
test "inflects the name of the helper module to test from the test case class" do
assert_equal ATestHelper, test_case.helper_class
assert test_case.ancestors.include?(ATestHelper)
end
test "a configured test controller is available" do
assert_kind_of ActionController::Base, controller
assert_equal '', controller.controller_path
end
test "helper class that is being tested is always included in view instance" do
self.class.helper_class.module_eval do
def render_from_helper
render :partial => 'customer', :collection => @customers
end
end
TestController.stubs(:controller_path).returns('test')
@customers = [stub(:name => 'Eloy'), stub(:name => 'Manfred')]
assert_match /Hello: EloyHello: Manfred/, render(:partial => 'test/from_helper')
end
test "no additional helpers should shared across test cases" do
assert !test_case.ancestors.include?(AnotherTestHelper)
assert_raise(NoMethodError) { send :from_another_helper }
end
test "is able to use routes" do
controller.request.assign_parameters('foo', 'index')
assert_equal '/foo', url_for
assert_equal '/bar', url_for(:controller => 'bar')
end
test "is able to use named routes" do
with_routing do |set|
set.draw { |map| map.resources :contents }
assert_equal 'http://test.host/contents/new', new_content_url
assert_equal 'http://test.host/contents/1', content_url(:id => 1)
end
end
test "named routes can be used from helper included in view" do
with_routing do |set|
set.draw { |map| map.resources :contents }
master_helper_module.module_eval do
def render_from_helper
new_content_url
end
end
assert_equal 'http://test.host/contents/new', render(:partial => 'test/from_helper')
end
end
test "is able to render partials with local variables" do
assert_equal 'Eloy', render('developers/developer', :developer => stub(:name => 'Eloy'))
assert_equal 'Eloy', render(:partial => 'developers/developer',
:locals => { :developer => stub(:name => 'Eloy') })
end
test "is able to render partials from templates and also use instance variables" do
TestController.stubs(:controller_path).returns('test')
@customers = [stub(:name => 'Eloy'), stub(:name => 'Manfred')]
assert_match /Hello: EloyHello: Manfred/, render(:file => 'test/list')
end
test "is able to make methods available to the view" do
master_helper_module.module_eval do
def render_from_helper; from_test_case end
end
assert_equal 'Word!', render(:partial => 'test/from_helper')
end
def from_test_case; 'Word!'; end
helper_method :from_test_case
end
class AssertionsTest < ActionView::TestCase
def render_from_helper
form_tag('/foo') do
concat render(:text => '<ul><li>foo</li></ul>')
end
end
helper_method :render_from_helper
test "uses the output_buffer for assert_select" do
render(:partial => 'test/from_helper')
assert_select 'form' do
assert_select 'li', :text => 'foo'
end
end
end
end
end
end

View file

@ -1,3 +1,11 @@
*2.3.5 (November 25, 2009)*
* Minor Bug Fixes and deprecation warnings
* 1.9 Compatibility
* Numerous fixes to the nested attributes functionality
*2.3.4 (September 4, 2009)*
* PostgreSQL: XML datatype support. #1874 [Leonardo Borges]

View file

@ -192,7 +192,7 @@ spec = Gem::Specification.new do |s|
s.files = s.files + Dir.glob( "#{dir}/**/*" ).delete_if { |item| item.include?( "\.svn" ) }
end
s.add_dependency('activesupport', '= 2.3.4' + PKG_BUILD)
s.add_dependency('activesupport', '= 2.3.5' + PKG_BUILD)
s.files.delete FIXTURES_ROOT + "/fixture_database.sqlite"
s.files.delete FIXTURES_ROOT + "/fixture_database_2.sqlite"

View file

@ -0,0 +1 @@
performance.sql

View file

@ -275,9 +275,10 @@ module ActiveRecord
# You can manipulate objects and associations before they are saved to the database, but there is some special behavior you should be
# aware of, mostly involving the saving of associated objects.
#
# Unless you enable the :autosave option on a <tt>has_one</tt>, <tt>belongs_to</tt>,
# <tt>has_many</tt>, or <tt>has_and_belongs_to_many</tt> association,
# in which case the members are always saved.
# Unless you set the :autosave option on a <tt>has_one</tt>, <tt>belongs_to</tt>,
# <tt>has_many</tt>, or <tt>has_and_belongs_to_many</tt> association. Setting it
# to +true+ will _always_ save the members, whereas setting it to +false+ will
# _never_ save the members.
#
# === One-to-one associations
#
@ -874,7 +875,9 @@ module ActiveRecord
# if the real class name is Person, you'll have to specify it with this option.
# [:conditions]
# Specify the conditions that the associated object must meet in order to be included as a +WHERE+
# SQL fragment, such as <tt>rank = 5</tt>.
# SQL fragment, such as <tt>rank = 5</tt>. Record creation from the association is scoped if a hash
# is used. <tt>has_one :account, :conditions => {:enabled => true}</tt> will create an enabled account with <tt>@company.create_account</tt>
# or <tt>@company.build_account</tt>.
# [:order]
# Specify the order in which the associated objects are returned as an <tt>ORDER BY</tt> SQL fragment,
# such as <tt>last_name, first_name DESC</tt>.
@ -1324,8 +1327,8 @@ module ActiveRecord
end
define_method("#{reflection.name.to_s.singularize}_ids=") do |new_value|
ids = (new_value || []).reject { |nid| nid.blank? }
send("#{reflection.name}=", reflection.klass.find(ids))
ids = (new_value || []).reject { |nid| nid.blank? }.map(&:to_i)
send("#{reflection.name}=", reflection.klass.find(ids).index_by(&:id).values_at(*ids))
end
end
end
@ -1408,7 +1411,7 @@ module ActiveRecord
if reflection.options.include?(:dependent)
# Add polymorphic type if the :as option is present
dependent_conditions = []
dependent_conditions << "#{reflection.primary_key_name} = \#{record.quoted_id}"
dependent_conditions << "#{reflection.primary_key_name} = \#{record.#{reflection.name}.send(:owner_quoted_id)}"
dependent_conditions << "#{reflection.options[:as]}_type = '#{base_class.name}'" if reflection.options[:as]
dependent_conditions << sanitize_sql(reflection.options[:conditions], reflection.quoted_table_name) if reflection.options[:conditions]
dependent_conditions << extra_conditions if extra_conditions

View file

@ -210,15 +210,14 @@ module ActiveRecord
# Forwards any missing method call to the \target.
def method_missing(method, *args)
if load_target
unless @target.respond_to?(method)
message = "undefined method `#{method.to_s}' for \"#{@target}\":#{@target.class.to_s}"
raise NoMethodError, message
end
if block_given?
@target.send(method, *args) { |*block_args| yield(*block_args) }
if @target.respond_to?(method)
if block_given?
@target.send(method, *args) { |*block_args| yield(*block_args) }
else
@target.send(method, *args)
end
else
@target.send(method, *args)
super
end
end
end

View file

@ -24,8 +24,8 @@ module ActiveRecord
def has_primary_key?
return @has_primary_key unless @has_primary_key.nil?
@has_primary_key = (ActiveRecord::Base.connection.supports_primary_key? &&
ActiveRecord::Base.connection.primary_key(@reflection.options[:join_table]))
@has_primary_key = (@owner.connection.supports_primary_key? &&
@owner.connection.primary_key(@reflection.options[:join_table]))
end
protected

Some files were not shown because too many files have changed in this diff Show more