2017-07-23 11:36:41 -04:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2016-08-06 12:50:17 -04:00
|
|
|
require "abstract_unit"
|
|
|
|
require "fileutils"
|
|
|
|
require "action_view/dependency_tracker"
|
2012-08-29 15:23:15 -04:00
|
|
|
|
2016-02-12 15:11:56 -05:00
|
|
|
class FixtureFinder < ActionView::LookupContext
|
2017-05-15 10:17:28 -04:00
|
|
|
FIXTURES_DIR = File.expand_path("../fixtures/digestor", __dir__)
|
2012-09-05 12:51:24 -04:00
|
|
|
|
2016-02-12 15:11:56 -05:00
|
|
|
def initialize(details = {})
|
2016-08-06 12:50:17 -04:00
|
|
|
super(ActionView::PathSet.new(["digestor", "digestor/api"]), details, [])
|
2016-06-14 17:23:44 -04:00
|
|
|
@rendered_format = :html
|
2014-03-13 11:56:29 -04:00
|
|
|
end
|
2012-08-29 15:23:15 -04:00
|
|
|
end
|
|
|
|
|
2016-06-15 17:56:17 -04:00
|
|
|
class ActionView::Digestor::Node
|
|
|
|
def flatten
|
|
|
|
[self] + children.flat_map(&:flatten)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-08-29 15:23:15 -04:00
|
|
|
class TemplateDigestorTest < ActionView::TestCase
|
|
|
|
def setup
|
2012-10-17 14:30:08 -04:00
|
|
|
@cwd = Dir.pwd
|
|
|
|
@tmp_dir = Dir.mktmpdir
|
|
|
|
|
2016-02-23 14:55:18 -05:00
|
|
|
ActionView::LookupContext::DetailsKey.clear
|
2012-10-17 14:30:08 -04:00
|
|
|
FileUtils.cp_r FixtureFinder::FIXTURES_DIR, @tmp_dir
|
|
|
|
Dir.chdir @tmp_dir
|
2012-08-29 15:23:15 -04:00
|
|
|
end
|
2012-09-05 12:51:24 -04:00
|
|
|
|
2012-08-29 15:23:15 -04:00
|
|
|
def teardown
|
2012-10-17 14:30:08 -04:00
|
|
|
Dir.chdir @cwd
|
|
|
|
FileUtils.rm_r @tmp_dir
|
2012-08-29 15:23:15 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def test_top_level_change_reflected
|
|
|
|
assert_digest_difference("messages/show") do
|
|
|
|
change_template("messages/show")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_explicit_dependency
|
|
|
|
assert_digest_difference("messages/show") do
|
|
|
|
change_template("messages/_message")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-12-21 16:51:41 -05:00
|
|
|
def test_explicit_dependency_in_multiline_erb_tag
|
|
|
|
assert_digest_difference("messages/show") do
|
|
|
|
change_template("messages/_form")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-07-15 17:32:45 -04:00
|
|
|
def test_explicit_dependency_wildcard
|
|
|
|
assert_digest_difference("events/index") do
|
|
|
|
change_template("events/_completed")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_explicit_dependency_wildcard_picks_up_added_file
|
2016-05-09 14:11:02 -04:00
|
|
|
disable_resolver_caching do
|
|
|
|
assert_digest_difference("events/index") do
|
|
|
|
add_template("events/_uncompleted")
|
|
|
|
end
|
2015-07-15 17:32:45 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_explicit_dependency_wildcard_picks_up_removed_file
|
2016-05-09 14:11:02 -04:00
|
|
|
disable_resolver_caching do
|
|
|
|
add_template("events/_subscribers_changed")
|
2015-07-15 17:32:45 -04:00
|
|
|
|
2016-05-09 14:11:02 -04:00
|
|
|
assert_digest_difference("events/index") do
|
|
|
|
remove_template("events/_subscribers_changed")
|
|
|
|
end
|
2015-07-15 17:32:45 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-08-29 15:23:15 -04:00
|
|
|
def test_second_level_dependency
|
|
|
|
assert_digest_difference("messages/show") do
|
|
|
|
change_template("comments/_comments")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_second_level_dependency_within_same_directory
|
|
|
|
assert_digest_difference("messages/show") do
|
|
|
|
change_template("messages/_header")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_third_level_dependency
|
|
|
|
assert_digest_difference("messages/show") do
|
|
|
|
change_template("comments/_comment")
|
|
|
|
end
|
|
|
|
end
|
2012-10-27 10:03:18 -04:00
|
|
|
|
2012-10-11 12:36:58 -04:00
|
|
|
def test_directory_depth_dependency
|
|
|
|
assert_digest_difference("level/below/index") do
|
|
|
|
change_template("level/below/_header")
|
|
|
|
end
|
|
|
|
end
|
2012-08-29 15:23:15 -04:00
|
|
|
|
|
|
|
def test_logging_of_missing_template
|
2014-03-21 11:29:00 -04:00
|
|
|
assert_logged "Couldn't find template for digesting: messages/something_missing" do
|
2012-08-29 15:23:15 -04:00
|
|
|
digest("messages/show")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2013-04-29 18:42:16 -04:00
|
|
|
def test_logging_of_missing_template_ending_with_number
|
2014-03-21 11:29:00 -04:00
|
|
|
assert_logged "Couldn't find template for digesting: messages/something_missing_1" do
|
2013-04-29 18:42:16 -04:00
|
|
|
digest("messages/show")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-05-07 13:17:45 -04:00
|
|
|
def test_logging_of_missing_template_for_dependencies
|
2017-03-22 13:58:32 -04:00
|
|
|
assert_logged "Couldn't find template for digesting: messages/something_missing" do
|
2015-05-07 13:17:45 -04:00
|
|
|
dependencies("messages/something_missing")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_logging_of_missing_template_for_nested_dependencies
|
2017-03-22 13:58:32 -04:00
|
|
|
assert_logged "Couldn't find template for digesting: messages/something_missing" do
|
2015-05-07 13:17:45 -04:00
|
|
|
nested_dependencies("messages/something_missing")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-02-13 04:28:05 -05:00
|
|
|
def test_getting_of_singly_nested_dependencies
|
|
|
|
singly_nested_dependencies = ["messages/header", "messages/form", "messages/message", "events/event", "comments/comment"]
|
2016-08-06 12:50:17 -04:00
|
|
|
assert_equal singly_nested_dependencies, nested_dependencies("messages/edit")
|
2016-02-13 04:28:05 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
def test_getting_of_doubly_nested_dependencies
|
2016-10-28 23:05:58 -04:00
|
|
|
doubly_nested = [{ "comments/comments" => ["comments/comment"] }, "messages/message"]
|
2016-08-06 12:50:17 -04:00
|
|
|
assert_equal doubly_nested, nested_dependencies("messages/peek")
|
2016-02-13 04:28:05 -05:00
|
|
|
end
|
|
|
|
|
2012-08-29 15:23:15 -04:00
|
|
|
def test_nested_template_directory
|
|
|
|
assert_digest_difference("messages/show") do
|
|
|
|
change_template("messages/actions/_move")
|
|
|
|
end
|
|
|
|
end
|
2012-09-05 12:51:24 -04:00
|
|
|
|
2016-02-16 18:10:25 -05:00
|
|
|
def test_nested_template_deps
|
2016-10-28 23:05:58 -04:00
|
|
|
nested_deps = ["messages/header", { "comments/comments" => ["comments/comment"] }, "messages/actions/move", "events/event", "messages/something_missing", "messages/something_missing_1", "messages/message", "messages/form"]
|
2016-02-16 18:10:25 -05:00
|
|
|
assert_equal nested_deps, nested_dependencies("messages/show")
|
|
|
|
end
|
|
|
|
|
2016-06-15 17:56:17 -04:00
|
|
|
def test_nested_template_deps_with_non_default_rendered_format
|
|
|
|
finder.rendered_format = nil
|
2016-10-28 23:05:58 -04:00
|
|
|
nested_deps = [{ "comments/comments" => ["comments/comment"] }]
|
2016-06-15 17:56:17 -04:00
|
|
|
assert_equal nested_deps, nested_dependencies("messages/thread")
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_template_formats_of_nested_deps_with_non_default_rendered_format
|
|
|
|
finder.rendered_format = nil
|
2016-06-15 18:24:26 -04:00
|
|
|
assert_equal [:json], tree_template_formats("messages/thread").uniq
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_template_formats_of_dependencies_with_same_logical_name_and_different_rendered_format
|
|
|
|
assert_equal [:html], tree_template_formats("messages/show").uniq
|
2016-06-15 17:56:17 -04:00
|
|
|
end
|
|
|
|
|
2018-03-18 09:59:47 -04:00
|
|
|
def test_template_dependencies_with_fallback_from_js_to_html_format
|
|
|
|
finder.rendered_format = :js
|
|
|
|
assert_equal ["comments/comment"], dependencies("comments/show")
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_template_digest_with_fallback_from_js_to_html_format
|
|
|
|
finder.rendered_format = :js
|
|
|
|
assert_digest_difference("comments/show") do
|
|
|
|
change_template("comments/_comment")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2013-07-07 12:44:16 -04:00
|
|
|
def test_recursion_in_renders
|
|
|
|
assert digest("level/recursion") # assert recursion is possible
|
|
|
|
assert_not_nil digest("level/recursion") # assert digest is stored
|
|
|
|
end
|
|
|
|
|
2013-07-19 10:45:14 -04:00
|
|
|
def test_chaining_the_top_template_on_recursion
|
2013-07-07 12:44:16 -04:00
|
|
|
assert digest("level/recursion") # assert recursion is possible
|
|
|
|
|
|
|
|
assert_digest_difference("level/recursion") do
|
|
|
|
change_template("level/recursion")
|
|
|
|
end
|
|
|
|
|
|
|
|
assert_not_nil digest("level/recursion") # assert digest is stored
|
|
|
|
end
|
|
|
|
|
2013-07-19 10:45:14 -04:00
|
|
|
def test_chaining_the_partial_template_on_recursion
|
2013-07-07 12:44:16 -04:00
|
|
|
assert digest("level/recursion") # assert recursion is possible
|
|
|
|
|
|
|
|
assert_digest_difference("level/recursion") do
|
|
|
|
change_template("level/_recursion")
|
|
|
|
end
|
|
|
|
|
|
|
|
assert_not_nil digest("level/recursion") # assert digest is stored
|
|
|
|
end
|
|
|
|
|
2012-08-29 15:23:15 -04:00
|
|
|
def test_dont_generate_a_digest_for_missing_templates
|
2016-08-06 12:50:17 -04:00
|
|
|
assert_equal "", digest("nothing/there")
|
2012-08-29 15:23:15 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def test_collection_dependency
|
|
|
|
assert_digest_difference("messages/index") do
|
|
|
|
change_template("messages/_message")
|
|
|
|
end
|
|
|
|
|
|
|
|
assert_digest_difference("messages/index") do
|
|
|
|
change_template("events/_event")
|
|
|
|
end
|
|
|
|
end
|
2012-09-05 12:51:24 -04:00
|
|
|
|
2012-08-29 15:23:15 -04:00
|
|
|
def test_collection_derived_from_record_dependency
|
|
|
|
assert_digest_difference("messages/show") do
|
|
|
|
change_template("events/_event")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2013-07-15 09:59:18 -04:00
|
|
|
def test_details_are_included_in_cache_key
|
|
|
|
# Cache the template digest.
|
2016-08-06 13:44:11 -04:00
|
|
|
@finder = FixtureFinder.new(formats: [:html])
|
2013-07-15 09:59:18 -04:00
|
|
|
old_digest = digest("events/_event")
|
|
|
|
|
|
|
|
# Change the template; the cached digest remains unchanged.
|
|
|
|
change_template("events/_event")
|
|
|
|
|
|
|
|
# The details are changed, so a new cache key is generated.
|
2016-02-12 15:11:56 -05:00
|
|
|
@finder = FixtureFinder.new
|
2013-07-15 09:59:18 -04:00
|
|
|
|
|
|
|
# The cache is busted.
|
|
|
|
assert_not_equal old_digest, digest("events/_event")
|
|
|
|
end
|
|
|
|
|
2012-08-30 07:01:25 -04:00
|
|
|
def test_extra_whitespace_in_render_partial
|
|
|
|
assert_digest_difference("messages/edit") do
|
|
|
|
change_template("messages/_form")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_extra_whitespace_in_render_named_partial
|
|
|
|
assert_digest_difference("messages/edit") do
|
|
|
|
change_template("messages/_header")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_extra_whitespace_in_render_record
|
|
|
|
assert_digest_difference("messages/edit") do
|
|
|
|
change_template("messages/_message")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_extra_whitespace_in_render_with_parenthesis
|
|
|
|
assert_digest_difference("messages/edit") do
|
|
|
|
change_template("events/_event")
|
|
|
|
end
|
|
|
|
end
|
2012-08-29 15:23:15 -04:00
|
|
|
|
2012-08-30 07:13:47 -04:00
|
|
|
def test_old_style_hash_in_render_invocation
|
|
|
|
assert_digest_difference("messages/edit") do
|
|
|
|
change_template("comments/_comment")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-03-01 12:59:56 -05:00
|
|
|
def test_variants
|
2015-07-18 15:51:46 -04:00
|
|
|
assert_digest_difference("messages/new", variants: [:iphone]) do
|
2014-03-01 12:59:56 -05:00
|
|
|
change_template("messages/new", :iphone)
|
|
|
|
change_template("messages/_header", :iphone)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2013-01-08 13:20:47 -05:00
|
|
|
def test_dependencies_via_options_results_in_different_digest
|
|
|
|
digest_plain = digest("comments/_comment")
|
|
|
|
digest_fridge = digest("comments/_comment", dependencies: ["fridge"])
|
|
|
|
digest_phone = digest("comments/_comment", dependencies: ["phone"])
|
|
|
|
digest_fridge_phone = digest("comments/_comment", dependencies: ["fridge", "phone"])
|
|
|
|
|
|
|
|
assert_not_equal digest_plain, digest_fridge
|
|
|
|
assert_not_equal digest_plain, digest_phone
|
|
|
|
assert_not_equal digest_plain, digest_fridge_phone
|
|
|
|
assert_not_equal digest_fridge, digest_phone
|
|
|
|
assert_not_equal digest_fridge, digest_fridge_phone
|
|
|
|
assert_not_equal digest_phone, digest_fridge_phone
|
|
|
|
end
|
|
|
|
|
2016-06-15 18:00:34 -04:00
|
|
|
def test_different_formats_with_same_logical_template_names_results_in_different_digests
|
|
|
|
html_digest = digest("comments/_comment", format: :html)
|
|
|
|
json_digest = digest("comments/_comment", format: :json)
|
|
|
|
|
|
|
|
assert_not_equal html_digest, json_digest
|
|
|
|
end
|
|
|
|
|
2013-10-14 18:06:50 -04:00
|
|
|
def test_digest_cache_cleanup_with_recursion
|
|
|
|
first_digest = digest("level/_recursion")
|
|
|
|
second_digest = digest("level/_recursion")
|
|
|
|
|
|
|
|
assert first_digest
|
|
|
|
|
|
|
|
# If the cache is cleaned up correctly, subsequent digests should return the same
|
2013-10-16 18:43:10 -04:00
|
|
|
assert_equal first_digest, second_digest
|
2013-10-14 18:06:50 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def test_digest_cache_cleanup_with_recursion_and_template_caching_off
|
2016-05-09 14:11:02 -04:00
|
|
|
disable_resolver_caching do
|
|
|
|
first_digest = digest("level/_recursion")
|
|
|
|
second_digest = digest("level/_recursion")
|
2013-10-16 18:43:10 -04:00
|
|
|
|
2016-05-09 14:11:02 -04:00
|
|
|
assert first_digest
|
2013-10-14 18:06:50 -04:00
|
|
|
|
2016-05-09 14:11:02 -04:00
|
|
|
# If the cache is cleaned up correctly, subsequent digests should return the same
|
|
|
|
assert_equal first_digest, second_digest
|
|
|
|
end
|
2013-10-14 18:06:50 -04:00
|
|
|
end
|
|
|
|
|
2012-08-29 15:23:15 -04:00
|
|
|
private
|
|
|
|
def assert_logged(message)
|
2012-09-05 12:51:24 -04:00
|
|
|
old_logger = ActionView::Base.logger
|
2012-08-29 15:23:15 -04:00
|
|
|
log = StringIO.new
|
2012-09-05 12:51:24 -04:00
|
|
|
ActionView::Base.logger = Logger.new(log)
|
2012-08-29 15:23:15 -04:00
|
|
|
|
2012-09-05 12:51:24 -04:00
|
|
|
begin
|
|
|
|
yield
|
|
|
|
|
|
|
|
log.rewind
|
|
|
|
assert_match message, log.read
|
|
|
|
ensure
|
|
|
|
ActionView::Base.logger = old_logger
|
|
|
|
end
|
2012-08-29 15:23:15 -04:00
|
|
|
end
|
|
|
|
|
2015-07-18 15:51:46 -04:00
|
|
|
def assert_digest_difference(template_name, options = {})
|
2014-03-01 12:59:56 -05:00
|
|
|
previous_digest = digest(template_name, options)
|
2016-02-18 11:23:26 -05:00
|
|
|
finder.digest_cache.clear
|
2012-08-29 15:23:15 -04:00
|
|
|
|
|
|
|
yield
|
|
|
|
|
2016-02-12 14:37:55 -05:00
|
|
|
assert_not_equal previous_digest, digest(template_name, options), "digest didn't change"
|
2016-02-18 11:23:26 -05:00
|
|
|
finder.digest_cache.clear
|
2012-08-29 15:23:15 -04:00
|
|
|
end
|
2012-09-05 12:51:24 -04:00
|
|
|
|
2014-03-01 12:59:56 -05:00
|
|
|
def digest(template_name, options = {})
|
|
|
|
options = options.dup
|
2016-06-14 17:23:44 -04:00
|
|
|
finder_options = options.extract!(:variants, :format)
|
|
|
|
|
|
|
|
finder.variants = finder_options[:variants] || []
|
|
|
|
finder.rendered_format = finder_options[:format] if finder_options[:format]
|
2014-03-13 11:55:54 -04:00
|
|
|
|
2016-02-18 18:02:10 -05:00
|
|
|
ActionView::Digestor.digest(name: template_name, finder: finder, dependencies: (options[:dependencies] || []))
|
2013-07-15 09:59:18 -04:00
|
|
|
end
|
|
|
|
|
2015-05-07 13:17:45 -04:00
|
|
|
def dependencies(template_name)
|
2016-02-18 18:06:41 -05:00
|
|
|
tree = ActionView::Digestor.tree(template_name, finder)
|
2016-02-16 18:10:25 -05:00
|
|
|
tree.children.map(&:name)
|
2015-05-07 13:17:45 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def nested_dependencies(template_name)
|
2016-02-18 18:06:41 -05:00
|
|
|
tree = ActionView::Digestor.tree(template_name, finder)
|
2016-02-16 18:10:25 -05:00
|
|
|
tree.children.map(&:to_dep_map)
|
2015-05-07 13:17:45 -04:00
|
|
|
end
|
|
|
|
|
2016-06-15 17:56:17 -04:00
|
|
|
def tree_template_formats(template_name)
|
|
|
|
tree = ActionView::Digestor.tree(template_name, finder)
|
2016-06-15 18:24:26 -04:00
|
|
|
tree.flatten.map(&:template).compact.flat_map(&:formats)
|
2016-06-15 17:56:17 -04:00
|
|
|
end
|
|
|
|
|
2016-05-09 14:11:02 -04:00
|
|
|
def disable_resolver_caching
|
|
|
|
old_caching, ActionView::Resolver.caching = ActionView::Resolver.caching, false
|
|
|
|
yield
|
|
|
|
ensure
|
|
|
|
ActionView::Resolver.caching = old_caching
|
|
|
|
end
|
|
|
|
|
2013-07-15 09:59:18 -04:00
|
|
|
def finder
|
|
|
|
@finder ||= FixtureFinder.new
|
2012-08-29 15:23:15 -04:00
|
|
|
end
|
2012-09-05 12:51:24 -04:00
|
|
|
|
2014-03-01 12:59:56 -05:00
|
|
|
def change_template(template_name, variant = nil)
|
|
|
|
variant = "+#{variant}" if variant.present?
|
|
|
|
|
|
|
|
File.open("digestor/#{template_name}.html#{variant}.erb", "w") do |f|
|
2012-08-29 15:23:15 -04:00
|
|
|
f.write "\nTHIS WAS CHANGED!"
|
|
|
|
end
|
|
|
|
end
|
2015-07-15 17:32:45 -04:00
|
|
|
alias_method :add_template, :change_template
|
|
|
|
|
|
|
|
def remove_template(template_name)
|
|
|
|
File.delete("digestor/#{template_name}.html.erb")
|
|
|
|
end
|
2012-08-29 15:23:15 -04:00
|
|
|
end
|