1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00
rails--rails/actionview/test/template/template_test.rb
Dov Murik d51e2eefd5 Improve detection of partial templates eligible for collection caching.
The regular expression which was used to detect partial templates that
begin with a `<% cache ... do %>` call missed some cases.  This commits
attempts to improve the detection for some cases such as multi-line
comments at the beginning of the template.  The different templates are
listed in two new unit test methods.

Note that specially crafted Ruby code can still evade such `cache`-call
detection: for example, a user might have its own method which itself
calls the Rails `cache` helper. In such a case, the template's code
doesn't start with a literal `cache` string and therefore will not be
eligible for collection caching.
2015-06-22 14:17:08 -04:00

231 lines
6.8 KiB
Ruby

# encoding: US-ASCII
require "abstract_unit"
require "logger"
class TestERBTemplate < ActiveSupport::TestCase
ERBHandler = ActionView::Template::Handlers::ERB.new
class LookupContext
def disable_cache
yield
end
def find_template(*args)
end
attr_accessor :formats
end
class Context
def initialize
@output_buffer = "original"
@virtual_path = nil
end
def hello
"Hello"
end
def apostrophe
"l'apostrophe"
end
def partial
ActionView::Template.new(
"<%= @virtual_path %>",
"partial",
ERBHandler,
:virtual_path => "partial"
)
end
def lookup_context
@lookup_context ||= LookupContext.new
end
def logger
ActiveSupport::Logger.new(STDERR)
end
def my_buffer
@output_buffer
end
end
def new_template(body = "<%= hello %>", details = { format: :html })
ActionView::Template.new(body, "hello template", details.fetch(:handler) { ERBHandler }, {:virtual_path => "hello"}.merge!(details))
end
def render(locals = {})
@template.render(@context, locals)
end
def setup
@context = Context.new
end
def test_basic_template
@template = new_template
assert_equal "Hello", render
end
def test_basic_template_does_html_escape
@template = new_template("<%= apostrophe %>")
assert_equal "l&#39;apostrophe", render
end
def test_text_template_does_not_html_escape
@template = new_template("<%= apostrophe %> <%== apostrophe %>", format: :text)
assert_equal "l'apostrophe l'apostrophe", render
end
def test_raw_template
@template = new_template("<%= hello %>", :handler => ActionView::Template::Handlers::Raw.new)
assert_equal "<%= hello %>", render
end
def test_template_loses_its_source_after_rendering
@template = new_template
render
assert_nil @template.source
end
def test_template_does_not_lose_its_source_after_rendering_if_it_does_not_have_a_virtual_path
@template = new_template("Hello", :virtual_path => nil)
render
assert_equal "Hello", @template.source
end
def test_locals
@template = new_template("<%= my_local %>")
@template.locals = [:my_local]
assert_equal "I am a local", render(:my_local => "I am a local")
end
def test_restores_buffer
@template = new_template
assert_equal "Hello", render
assert_equal "original", @context.my_buffer
end
def test_virtual_path
@template = new_template("<%= @virtual_path %>" \
"<%= partial.render(self, {}) %>" \
"<%= @virtual_path %>")
assert_equal "hellopartialhello", render
end
def test_refresh_with_templates
@template = new_template("Hello", :virtual_path => "test/foo/bar")
@template.locals = [:key]
@context.lookup_context.expects(:find_template).with("bar", %w(test/foo), false, [:key]).returns("template")
assert_equal "template", @template.refresh(@context)
end
def test_refresh_with_partials
@template = new_template("Hello", :virtual_path => "test/_foo")
@template.locals = [:key]
@context.lookup_context.expects(:find_template).with("foo", %w(test), true, [:key]).returns("partial")
assert_equal "partial", @template.refresh(@context)
end
def test_refresh_raises_an_error_without_virtual_path
@template = new_template("Hello", :virtual_path => nil)
assert_raise RuntimeError do
@template.refresh(@context)
end
end
def test_resulting_string_is_utf8
@template = new_template
assert_equal Encoding::UTF_8, render.encoding
end
def test_no_magic_comment_word_with_utf_8
@template = new_template("hello \u{fc}mlat")
assert_equal Encoding::UTF_8, render.encoding
assert_equal "hello \u{fc}mlat", render
end
# This test ensures that if the default_external
# is set to something other than UTF-8, we don't
# get any errors and get back a UTF-8 String.
def test_default_external_works
with_external_encoding "ISO-8859-1" do
@template = new_template("hello \xFCmlat")
assert_equal Encoding::UTF_8, render.encoding
assert_equal "hello \u{fc}mlat", render
end
end
def test_encoding_can_be_specified_with_magic_comment
@template = new_template("# encoding: ISO-8859-1\nhello \xFCmlat")
assert_equal Encoding::UTF_8, render.encoding
assert_equal "\nhello \u{fc}mlat", render
end
# TODO: This is currently handled inside ERB. The case of explicitly
# lying about encodings via the normal Rails API should be handled
# inside Rails.
def test_lying_with_magic_comment
assert_raises(ActionView::Template::Error) do
@template = new_template("# encoding: UTF-8\nhello \xFCmlat", :virtual_path => nil)
render
end
end
def test_encoding_can_be_specified_with_magic_comment_in_erb
with_external_encoding Encoding::UTF_8 do
@template = new_template("<%# encoding: ISO-8859-1 %>hello \xFCmlat", :virtual_path => nil)
assert_equal Encoding::UTF_8, render.encoding
assert_equal "hello \u{fc}mlat", render
end
end
def test_error_when_template_isnt_valid_utf8
e = assert_raises ActionView::Template::Error do
@template = new_template("hello \xFCmlat", :virtual_path => nil)
render
end
assert_match(/\xFC/, e.message)
end
def test_not_eligible_for_collection_caching_without_cache_call
[
"<%= 'Hello' %>",
"<% cache_customer = 42 %>",
"<% cache customer.name do %><% end %>"
].each do |body|
template = new_template(body, virtual_path: "test/foo/_customer")
assert_not template.eligible_for_collection_caching?, "Template #{body.inspect} should not be eligible for collection caching"
end
end
def test_eligible_for_collection_caching_with_cache_call
[
"<% cache customer do %><% end %>",
"<% cache(customer) do %><% end %>",
"<% cache( customer) do %><% end %>",
"<% cache( customer ) do %><% end %>",
"<%cache customer do %><% end %>",
"<% cache customer do %><% end %>",
" <% cache customer do %>\n<% end %>\n",
"<%# comment %><% cache customer do %><% end %>",
"<%# comment %>\n<% cache customer do %><% end %>",
"<%# comment\n line 2\n line 3 %>\n<% cache customer do %><% end %>",
"<%# comment 1 %>\n<%# comment 2 %>\n<% cache customer do %><% end %>"
].each do |body|
template = new_template(body, virtual_path: "test/foo/_customer")
assert template.eligible_for_collection_caching?, "Template #{body.inspect} should be eligible for collection caching"
end
end
def with_external_encoding(encoding)
old = Encoding.default_external
Encoding::Converter.new old, encoding if old != encoding
silence_warnings { Encoding.default_external = encoding }
yield
ensure
silence_warnings { Encoding.default_external = old }
end
end