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/resolver_shared_tests.rb
John Hawthorn e53c45b80c Introduce Resolver::PathParser
The template resolver is supposed to determine the handler, format, and
variant from the path in extract_handler_and_format_and_variant.

Previously this behaviour was close but didn't exactly match the
behaviour of finding templates, and in some cases (particularly with
handlers or formats missing) would return incorrect results.

This commit introduces Resolver::PathParser, a class which should be
able to accurately from any path inside a view directory be able to tell
us exactly the prefix, partial, variant, locale, format, variant, and
handler of that template.

This works by building a building a regexp from the known handlers and
file types. This requires that any resolvers have their cache cleared
when new handlers or types are registered (this was already somewhat the
requirement, since resolver lookups are cached, but this makes it
necessary in more situations).
2020-05-19 18:55:10 -07:00

239 lines
9.4 KiB
Ruby

# frozen_string_literal: true
module ResolverSharedTests
attr_reader :tmpdir
def run(*args)
capture_exceptions do
Dir.mktmpdir(nil, __dir__) { |dir| @tmpdir = dir; super }
end
end
def with_file(filename, source = "File at #{filename}")
path = File.join(tmpdir, filename)
FileUtils.mkdir_p(File.dirname(path))
File.write(path, source)
end
def context
@context ||= ActionView::LookupContext.new(resolver)
end
def test_can_find_with_no_extensions
with_file "test/hello_world", "Hello default!"
templates = resolver.find_all("hello_world", "test", false, locale: [:en], formats: [:html], variants: [:phone], handlers: [:erb])
assert_equal 1, templates.size
assert_equal "Hello default!", templates[0].source
assert_equal "test/hello_world", templates[0].virtual_path
assert_nil templates[0].format
assert_nil templates[0].variant
assert_kind_of ActionView::Template::Handlers::Raw, templates[0].handler
end
def test_can_find_with_just_handler
with_file "test/hello_world.erb", "Hello erb!"
templates = resolver.find_all("hello_world", "test", false, locale: [:en], formats: [:html], variants: [:phone], handlers: [:erb])
assert_equal 1, templates.size
assert_equal "Hello erb!", templates[0].source
assert_equal "test/hello_world", templates[0].virtual_path
assert_nil templates[0].format
assert_nil templates[0].variant
assert_kind_of ActionView::Template::Handlers::ERB, templates[0].handler
end
def test_can_find_with_format_and_handler
with_file "test/hello_world.text.builder", "Hello plain text!"
templates = resolver.find_all("hello_world", "test", false, locale: [:en], formats: [:html, :text], variants: [:phone], handlers: [:erb, :builder])
assert_equal 1, templates.size
assert_equal "Hello plain text!", templates[0].source
assert_equal "test/hello_world", templates[0].virtual_path
assert_equal :text, templates[0].format
assert_nil templates[0].variant
assert_kind_of ActionView::Template::Handlers::Builder, templates[0].handler
end
def test_can_find_with_variant_format_and_handler
with_file "test/hello_world.html+phone.erb", "Hello plain text!"
templates = resolver.find_all("hello_world", "test", false, locale: [:en], formats: [:html], variants: [:phone], handlers: [:erb])
assert_equal 1, templates.size
assert_equal "Hello plain text!", templates[0].source
assert_equal "test/hello_world", templates[0].virtual_path
assert_equal :html, templates[0].format
assert_equal "phone", templates[0].variant
assert_kind_of ActionView::Template::Handlers::ERB, templates[0].handler
end
def test_can_find_with_any_variant_format_and_handler
with_file "test/hello_world.html+phone.erb", "Hello plain text!"
templates = resolver.find_all("hello_world", "test", false, locale: [:en], formats: [:html], variants: :any, handlers: [:erb])
assert_equal 1, templates.size
assert_equal "Hello plain text!", templates[0].source
assert_equal "test/hello_world", templates[0].virtual_path
assert_equal :html, templates[0].format
assert_equal "phone", templates[0].variant
assert_kind_of ActionView::Template::Handlers::ERB, templates[0].handler
end
def test_can_find_when_special_chars_in_path
dir = "test +()[]{}"
with_file "#{dir}/hello_world", "Hello funky path!"
templates = resolver.find_all("hello_world", dir, false, locale: [:en], formats: [:html], variants: [:phone], handlers: [:erb])
assert_equal 1, templates.size
assert_equal "Hello funky path!", templates[0].source
assert_equal "#{dir}/hello_world", templates[0].virtual_path
end
def test_doesnt_find_template_with_wrong_details
with_file "test/hello_world.html.erb", "Hello plain text!"
templates = resolver.find_all("hello_world", "test", false, locale: [], formats: [:xml], variants: :any, handlers: [:builder])
assert_equal 0, templates.size
templates = resolver.find_all("hello_world", "test", false, locale: [], formats: [:xml], variants: :any, handlers: [:erb])
assert_equal 0, templates.size
end
def test_found_template_is_cached
with_file "test/hello_world.html.erb", "Hello HTML!"
a = context.find("hello_world", "test", false, [], {})
b = context.find("hello_world", "test", false, [], {})
assert_same a, b
end
def test_different_templates_when_cache_disabled
with_file "test/hello_world.html.erb", "Hello HTML!"
a = context.find("hello_world", "test", false, [], {})
b = context.disable_cache { context.find("hello_world", "test", false, [], {}) }
c = context.find("hello_world", "test", false, [], {})
# disable_cache should give us a new object
assert_not_same a, b
# but it should not clear the cache
assert_same a, c
end
def test_same_template_from_different_details_is_same_object
with_file "test/hello_world.html.erb", "Hello HTML!"
a = context.find("hello_world", "test", false, [], locale: [:en])
b = context.find("hello_world", "test", false, [], locale: [:fr])
assert_same a, b
end
def test_templates_with_optional_locale_shares_common_object
with_file "test/hello_world.text.erb", "Generic plain text!"
with_file "test/hello_world.fr.text.erb", "Texte en Francais!"
en = context.find_all("hello_world", "test", false, [], locale: [:en])
fr = context.find_all("hello_world", "test", false, [], locale: [:fr])
assert_equal 1, en.size
assert_equal 2, fr.size
assert_equal "Generic plain text!", en[0].source
assert_equal "Texte en Francais!", fr[0].source
assert_equal "Generic plain text!", fr[1].source
assert_same en[0], fr[1]
end
def test_templates_sort_by_formats_json_first
with_file "test/hello_world.html.erb", "Hello HTML!"
with_file "test/hello_world.json.builder", "Hello JSON!"
templates = resolver.find_all("hello_world", "test", false, locale: [], formats: [:json, :html], variants: :any, handlers: [:erb, :builder])
assert_equal 2, templates.size
assert_equal "Hello JSON!", templates[0].source
assert_equal :json, templates[0].format
assert_equal "Hello HTML!", templates[1].source
assert_equal :html, templates[1].format
end
def test_templates_sort_by_formats_html_first
with_file "test/hello_world.html.erb", "Hello HTML!"
with_file "test/hello_world.json.builder", "Hello JSON!"
templates = resolver.find_all("hello_world", "test", false, locale: [], formats: [:html, :json], variants: :any, handlers: [:erb, :builder])
assert_equal 2, templates.size
assert_equal "Hello HTML!", templates[0].source
assert_equal :html, templates[0].format
assert_equal "Hello JSON!", templates[1].source
assert_equal :json, templates[1].format
end
def test_templates_with_variant
with_file "test/hello_world.html+mobile.erb", "Hello HTML!"
templates = resolver.find_all("hello_world", "test", false, locale: [], formats: [:html, :json], variants: :any, handlers: [:erb, :builder])
assert_equal 1, templates.size
assert_equal "Hello HTML!", templates[0].source
assert_kind_of ActionView::Template::Handlers::ERB, templates[0].handler
assert_equal :html, templates[0].format
assert_equal "mobile", templates[0].variant
end
def test_finds_variants_in_order
with_file "test/hello_world.html+tricorder.erb", "Hello Spock!"
with_file "test/hello_world.html+lcars.erb", "Hello Geordi!"
tricorder = context.find("hello_world", "test", false, [], { variants: [:tricorder] })
lcars = context.find("hello_world", "test", false, [], { variants: [:lcars] })
assert_equal "Hello Spock!", tricorder.source
assert_equal "tricorder", tricorder.variant
assert_equal "Hello Geordi!", lcars.source
assert_equal "lcars", lcars.variant
templates = context.find_all("hello_world", "test", false, [], { variants: [:tricorder, :lcars] })
assert_equal [tricorder, lcars], templates
templates = context.find_all("hello_world", "test", false, [], { variants: [:lcars, :tricorder] })
assert_equal [lcars, tricorder], templates
end
def test_templates_no_format_with_variant
with_file "test/hello_world+mobile.erb", "Hello HTML!"
templates = resolver.find_all("hello_world", "test", false, locale: [], formats: [:html, :json], variants: :any, handlers: [:erb, :builder])
assert_equal 1, templates.size
assert_equal "Hello HTML!", templates[0].source
assert_kind_of ActionView::Template::Handlers::ERB, templates[0].handler
assert_nil templates[0].format
assert_equal "mobile", templates[0].variant
end
def test_templates_no_format_or_handler_with_variant
with_file "test/hello_world+mobile", "Hello HTML!"
templates = resolver.find_all("hello_world", "test", false, locale: [], formats: [:html, :json], variants: :any, handlers: [:erb, :builder])
assert_equal 1, templates.size
assert_equal "Hello HTML!", templates[0].source
assert_kind_of ActionView::Template::Handlers::Raw, templates[0].handler
assert_nil templates[0].format
assert_equal "mobile", templates[0].variant
end
def test_virtual_path_is_preserved_with_dot
with_file "test/hello_world.html.erb", "Hello html!"
template = assert_deprecated { context.find("hello_world.html", "test", false, [], {}) }
assert_equal "test/hello_world.html", template.virtual_path
template = context.find("hello_world", "test", false, [], {})
assert_equal "test/hello_world", template.virtual_path
end
end