Merge pull request #1620 from Shopify/use-partials-test-option

Use assert_template_result partials option to specify file system state
This commit is contained in:
Dylan Thacker-Smith
2022-09-13 15:36:50 -04:00
committed by GitHub
3 changed files with 147 additions and 150 deletions
+72 -67
View File
@@ -3,44 +3,13 @@
require 'test_helper'
class TestFileSystem
PARTIALS = {
"nested_template" => "{% include 'header' %} {% include 'body' %} {% include 'footer' %}",
"body" => "body {% include 'body_detail' %}",
}
def read_template_file(template_path)
case template_path
when "product"
"Product: {{ product.title }} "
when "product_alias"
"Product: {{ product.title }} "
when "locale_variables"
"Locale: {{echo1}} {{echo2}}"
when "variant"
"Variant: {{ variant.title }}"
when "nested_template"
"{% include 'header' %} {% include 'body' %} {% include 'footer' %}"
when "body"
"body {% include 'body_detail' %}"
when "nested_product_template"
"Product: {{ nested_product_template.title }} {%include 'details'%} "
when "recursively_nested_template"
"-{% include 'recursively_nested_template' %}"
when "pick_a_source"
"from TestFileSystem"
when 'assignments'
"{% assign foo = 'bar' %}"
when 'break'
"{% break %}"
else
template_path
end
PARTIALS[template_path] || template_path
end
end
@@ -81,7 +50,11 @@ class IncludeTagTest < Minitest::Test
include Liquid
def setup
Liquid::Template.file_system = TestFileSystem.new
@default_file_system = Liquid::Template.file_system
end
def teardown
Liquid::Template.file_system = @default_file_system
end
def test_include_tag_looks_for_file_system_in_registers_first
@@ -92,63 +65,85 @@ class IncludeTagTest < Minitest::Test
def test_include_tag_with
assert_template_result("Product: Draft 151cm ",
"{% include 'product' with products[0] %}",
{ "products" => [{ 'title' => 'Draft 151cm' }, { 'title' => 'Element 155cm' }] })
{ "products" => [{ 'title' => 'Draft 151cm' }, { 'title' => 'Element 155cm' }] },
partials: { "product" => "Product: {{ product.title }} " })
end
def test_include_tag_with_alias
assert_template_result("Product: Draft 151cm ",
"{% include 'product_alias' with products[0] as product %}",
{ "products" => [{ 'title' => 'Draft 151cm' }, { 'title' => 'Element 155cm' }] })
{ "products" => [{ 'title' => 'Draft 151cm' }, { 'title' => 'Element 155cm' }] },
partials: { "product_alias" => "Product: {{ product.title }} " })
end
def test_include_tag_for_alias
assert_template_result("Product: Draft 151cm Product: Element 155cm ",
"{% include 'product_alias' for products as product %}",
{ "products" => [{ 'title' => 'Draft 151cm' }, { 'title' => 'Element 155cm' }] })
{ "products" => [{ 'title' => 'Draft 151cm' }, { 'title' => 'Element 155cm' }] },
partials: { "product_alias" => "Product: {{ product.title }} " })
end
def test_include_tag_with_default_name
assert_template_result("Product: Draft 151cm ",
"{% include 'product' %}", { "product" => { 'title' => 'Draft 151cm' } })
"{% include 'product' %}", { "product" => { 'title' => 'Draft 151cm' } },
partials: { "product" => "Product: {{ product.title }} " })
end
def test_include_tag_for
assert_template_result("Product: Draft 151cm Product: Element 155cm ",
"{% include 'product' for products %}",
{ "products" => [{ 'title' => 'Draft 151cm' }, { 'title' => 'Element 155cm' }] })
{ "products" => [{ 'title' => 'Draft 151cm' }, { 'title' => 'Element 155cm' }] },
partials: { "product" => "Product: {{ product.title }} " })
end
def test_include_tag_with_local_variables
assert_template_result("Locale: test123 ", "{% include 'locale_variables' echo1: 'test123' %}")
assert_template_result("Locale: test123 ", "{% include 'locale_variables' echo1: 'test123' %}",
partials: { "locale_variables" => "Locale: {{echo1}} {{echo2}}" })
end
def test_include_tag_with_multiple_local_variables
assert_template_result("Locale: test123 test321",
"{% include 'locale_variables' echo1: 'test123', echo2: 'test321' %}")
"{% include 'locale_variables' echo1: 'test123', echo2: 'test321' %}",
partials: { "locale_variables" => "Locale: {{echo1}} {{echo2}}" })
end
def test_include_tag_with_multiple_local_variables_from_context
assert_template_result("Locale: test123 test321",
"{% include 'locale_variables' echo1: echo1, echo2: more_echos.echo2 %}",
{ 'echo1' => 'test123', 'more_echos' => { "echo2" => 'test321' } })
{ 'echo1' => 'test123', 'more_echos' => { "echo2" => 'test321' } },
partials: { "locale_variables" => "Locale: {{echo1}} {{echo2}}" })
end
def test_included_templates_assigns_variables
assert_template_result("bar", "{% include 'assignments' %}{{ foo }}")
assert_template_result("bar", "{% include 'assignments' %}{{ foo }}",
partials: { 'assignments' => "{% assign foo = 'bar' %}" })
end
def test_nested_include_tag
assert_template_result("body body_detail", "{% include 'body' %}")
partials = { "body" => "body {% include 'body_detail' %}", "body_detail" => "body_detail" }
assert_template_result("body body_detail", "{% include 'body' %}", partials: partials)
assert_template_result("header body body_detail footer", "{% include 'nested_template' %}")
partials = partials.merge({
"nested_template" => "{% include 'header' %} {% include 'body' %} {% include 'footer' %}",
"header" => "header",
"footer" => "footer",
})
assert_template_result("header body body_detail footer", "{% include 'nested_template' %}", partials: partials)
end
def test_nested_include_with_variable
partials = {
"nested_product_template" => "Product: {{ nested_product_template.title }} {%include 'details'%} ",
"details" => "details",
}
assert_template_result("Product: Draft 151cm details ",
"{% include 'nested_product_template' with product %}", { "product" => { "title" => 'Draft 151cm' } })
"{% include 'nested_product_template' with product %}", { "product" => { "title" => 'Draft 151cm' } },
partials: partials)
assert_template_result("Product: Draft 151cm details Product: Element 155cm details ",
"{% include 'nested_product_template' for products %}", { "products" => [{ "title" => 'Draft 151cm' }, { "title" => 'Element 155cm' }] })
"{% include 'nested_product_template' for products %}", { "products" => [{ "title" => 'Draft 151cm' }, { "title" => 'Element 155cm' }] },
partials: partials)
end
def test_recursively_included_template_does_not_produce_endless_loop
@@ -166,11 +161,15 @@ class IncludeTagTest < Minitest::Test
end
def test_dynamically_choosen_template
assert_template_result("Test123", "{% include template %}", { "template" => 'Test123' })
assert_template_result("Test321", "{% include template %}", { "template" => 'Test321' })
assert_template_result("Test123", "{% include template %}", { "template" => 'Test123' },
partials: { "Test123" => "Test123" })
assert_template_result("Test321", "{% include template %}", { "template" => 'Test321' },
partials: { "Test321" => "Test321" })
assert_template_result("Product: Draft 151cm ", "{% include template for product %}",
{ "template" => 'product', 'product' => { 'title' => 'Draft 151cm' } })
{ "template" => 'product', 'product' => { 'title' => 'Draft 151cm' } },
partials: { "product" => "Product: {{ product.title }} " })
end
def test_include_tag_caches_second_read_of_same_partial
@@ -192,7 +191,8 @@ class IncludeTagTest < Minitest::Test
end
def test_include_tag_within_if_statement
assert_template_result("foo_if_true", "{% if true %}{% include 'foo_if_true' %}{% endif %}")
assert_template_result("foo_if_true", "{% if true %}{% include 'foo_if_true' %}{% endif %}",
partials: { "foo_if_true" => "foo_if_true" })
end
def test_custom_include_tag
@@ -226,6 +226,7 @@ class IncludeTagTest < Minitest::Test
end
def test_passing_options_to_included_templates
Liquid::Template.file_system = TestFileSystem.new
assert_raises(Liquid::SyntaxError) do
Template.parse("{% include template %}", error_mode: :strict).render!("template" => '{{ "X" || downcase }}')
end
@@ -241,27 +242,30 @@ class IncludeTagTest < Minitest::Test
end
def test_render_raise_argument_error_when_template_is_undefined
assert_raises(Liquid::ArgumentError) do
template = Liquid::Template.parse('{% include undefined_variable %}')
template.render!
end
assert_raises(Liquid::ArgumentError) do
template = Liquid::Template.parse('{% include nil %}')
template.render!
end
assert_template_result("Liquid error (line 1): Argument error in tag 'include' - Illegal template name",
"{% include undefined_variable %}", render_errors: true)
assert_template_result("Liquid error (line 1): Argument error in tag 'include' - Illegal template name",
"{% include nil %}", render_errors: true)
end
def test_including_via_variable_value
assert_template_result("from TestFileSystem", "{% assign page = 'pick_a_source' %}{% include page %}")
assert_template_result("from TestFileSystem", "{% assign page = 'pick_a_source' %}{% include page %}",
partials: { "pick_a_source" => "from TestFileSystem" })
partials = { "product" => "Product: {{ product.title }} " }
assert_template_result("Product: Draft 151cm ", "{% assign page = 'product' %}{% include page %}",
{ "product" => { 'title' => 'Draft 151cm' } })
{ "product" => { 'title' => 'Draft 151cm' } },
partials: partials)
assert_template_result("Product: Draft 151cm ", "{% assign page = 'product' %}{% include page for foo %}",
{ "foo" => { 'title' => 'Draft 151cm' } })
{ "foo" => { 'title' => 'Draft 151cm' } },
partials: partials)
end
def test_including_with_strict_variables
Liquid::Template.file_system = StubFileSystem.new({ "simple" => "simple" })
template = Liquid::Template.parse("{% include 'simple' %}", error_mode: :warn)
template.render(nil, strict_variables: true)
@@ -270,6 +274,7 @@ class IncludeTagTest < Minitest::Test
def test_break_through_include
assert_template_result("1", "{% for i in (1..3) %}{{ i }}{% break %}{{ i }}{% endfor %}")
assert_template_result("1", "{% for i in (1..3) %}{{ i }}{% include 'break' %}{{ i }}{% endfor %}")
assert_template_result("1", "{% for i in (1..3) %}{{ i }}{% include 'break' %}{{ i }}{% endfor %}",
partials: { 'break' => "{% break %}" })
end
end # IncludeTagTest
+71 -83
View File
@@ -6,53 +6,52 @@ class RenderTagTest < Minitest::Test
include Liquid
def test_render_with_no_arguments
Liquid::Template.file_system = StubFileSystem.new('source' => 'rendered content')
assert_template_result('rendered content', '{% render "source" %}')
assert_template_result('rendered content', '{% render "source" %}',
partials: { 'source' => 'rendered content' })
end
def test_render_tag_looks_for_file_system_in_registers_first
file_system = StubFileSystem.new('pick_a_source' => 'from register file system')
assert_equal('from register file system',
Template.parse('{% render "pick_a_source" %}').render!({}, registers: { file_system: file_system }))
assert_template_result('from register file system', '{% render "pick_a_source" %}',
partials: { 'pick_a_source' => 'from register file system' })
end
def test_render_passes_named_arguments_into_inner_scope
Liquid::Template.file_system = StubFileSystem.new('product' => '{{ inner_product.title }}')
assert_template_result('My Product', '{% render "product", inner_product: outer_product %}',
{ 'outer_product' => { 'title' => 'My Product' } })
{ 'outer_product' => { 'title' => 'My Product' } },
partials: { 'product' => '{{ inner_product.title }}' })
end
def test_render_accepts_literals_as_arguments
Liquid::Template.file_system = StubFileSystem.new('snippet' => '{{ price }}')
assert_template_result('123', '{% render "snippet", price: 123 %}')
assert_template_result('123', '{% render "snippet", price: 123 %}',
partials: { 'snippet' => '{{ price }}' })
end
def test_render_accepts_multiple_named_arguments
Liquid::Template.file_system = StubFileSystem.new('snippet' => '{{ one }} {{ two }}')
assert_template_result('1 2', '{% render "snippet", one: 1, two: 2 %}')
assert_template_result('1 2', '{% render "snippet", one: 1, two: 2 %}',
partials: { 'snippet' => '{{ one }} {{ two }}' })
end
def test_render_does_not_inherit_parent_scope_variables
Liquid::Template.file_system = StubFileSystem.new('snippet' => '{{ outer_variable }}')
assert_template_result('', '{% assign outer_variable = "should not be visible" %}{% render "snippet" %}')
assert_template_result('', '{% assign outer_variable = "should not be visible" %}{% render "snippet" %}',
partials: { 'snippet' => '{{ outer_variable }}' })
end
def test_render_does_not_inherit_variable_with_same_name_as_snippet
Liquid::Template.file_system = StubFileSystem.new('snippet' => '{{ snippet }}')
assert_template_result('', "{% assign snippet = 'should not be visible' %}{% render 'snippet' %}")
assert_template_result('', "{% assign snippet = 'should not be visible' %}{% render 'snippet' %}",
partials: { 'snippet' => '{{ snippet }}' })
end
def test_render_does_not_mutate_parent_scope
Liquid::Template.file_system = StubFileSystem.new('snippet' => '{% assign inner = 1 %}')
assert_template_result('', "{% render 'snippet' %}{{ inner }}")
assert_template_result('', "{% render 'snippet' %}{{ inner }}",
partials: { 'snippet' => '{% assign inner = 1 %}' })
end
def test_nested_render_tag
Liquid::Template.file_system = StubFileSystem.new(
'one' => "one {% render 'two' %}",
'two' => 'two'
)
assert_template_result('one two', "{% render 'one' %}")
assert_template_result('one two', "{% render 'one' %}",
partials: {
'one' => "one {% render 'two' %}",
'two' => 'two',
})
end
def test_recursively_rendered_template_does_not_produce_endless_loop
@@ -73,11 +72,7 @@ class RenderTagTest < Minitest::Test
end
def test_dynamically_choosen_templates_are_not_allowed
Liquid::Template.file_system = StubFileSystem.new('snippet' => 'should not be rendered')
assert_raises(Liquid::SyntaxError) do
Liquid::Template.parse("{% assign name = 'snippet' %}{% render name %}")
end
assert_syntax_error("{% assign name = 'snippet' %}{% render name %}")
end
def test_include_tag_caches_second_read_of_same_partial
@@ -101,36 +96,36 @@ class RenderTagTest < Minitest::Test
end
def test_render_tag_within_if_statement
Liquid::Template.file_system = StubFileSystem.new('snippet' => 'my message')
assert_template_result('my message', '{% if true %}{% render "snippet" %}{% endif %}')
assert_template_result('my message', '{% if true %}{% render "snippet" %}{% endif %}',
partials: { 'snippet' => 'my message' })
end
def test_break_through_render
Liquid::Template.file_system = StubFileSystem.new('break' => '{% break %}')
assert_template_result('1', '{% for i in (1..3) %}{{ i }}{% break %}{{ i }}{% endfor %}')
assert_template_result('112233', '{% for i in (1..3) %}{{ i }}{% render "break" %}{{ i }}{% endfor %}')
options = { partials: { 'break' => '{% break %}' } }
assert_template_result('1', '{% for i in (1..3) %}{{ i }}{% break %}{{ i }}{% endfor %}', **options)
assert_template_result('112233', '{% for i in (1..3) %}{{ i }}{% render "break" %}{{ i }}{% endfor %}', **options)
end
def test_increment_is_isolated_between_renders
Liquid::Template.file_system = StubFileSystem.new('incr' => '{% increment %}')
assert_template_result('010', '{% increment %}{% increment %}{% render "incr" %}')
assert_template_result('010', '{% increment %}{% increment %}{% render "incr" %}',
partials: { 'incr' => '{% increment %}' })
end
def test_decrement_is_isolated_between_renders
Liquid::Template.file_system = StubFileSystem.new('decr' => '{% decrement %}')
assert_template_result('-1-2-1', '{% decrement %}{% decrement %}{% render "decr" %}')
assert_template_result('-1-2-1', '{% decrement %}{% decrement %}{% render "decr" %}',
partials: { 'decr' => '{% decrement %}' })
end
def test_includes_will_not_render_inside_render_tag
Liquid::Template.file_system = StubFileSystem.new(
'foo' => 'bar',
'test_include' => '{% include "foo" %}'
assert_template_result(
'Liquid error (test_include line 1): include usage is not allowed in this context',
'{% render "test_include" %}',
render_errors: true,
partials: {
'foo' => 'bar',
'test_include' => '{% include "foo" %}',
}
)
exc = assert_raises(Liquid::DisabledError) do
Liquid::Template.parse('{% render "test_include" %}').render!
end
assert_equal('Liquid error: include usage is not allowed in this context', exc.message)
end
def test_includes_will_not_render_inside_nested_sibling_tags
@@ -148,74 +143,67 @@ class RenderTagTest < Minitest::Test
end
def test_render_tag_with
Liquid::Template.file_system = StubFileSystem.new(
'product' => "Product: {{ product.title }} ",
'product_alias' => "Product: {{ product.title }} ",
)
assert_template_result("Product: Draft 151cm ",
"{% render 'product' with products[0] %}",
{ "products" => [{ 'title' => 'Draft 151cm' }, { 'title' => 'Element 155cm' }] })
{ "products" => [{ 'title' => 'Draft 151cm' }, { 'title' => 'Element 155cm' }] },
partials: {
'product' => "Product: {{ product.title }} ",
'product_alias' => "Product: {{ product.title }} ",
})
end
def test_render_tag_with_alias
Liquid::Template.file_system = StubFileSystem.new(
'product' => "Product: {{ product.title }} ",
'product_alias' => "Product: {{ product.title }} ",
)
assert_template_result("Product: Draft 151cm ",
"{% render 'product_alias' with products[0] as product %}",
{ "products" => [{ 'title' => 'Draft 151cm' }, { 'title' => 'Element 155cm' }] })
{ "products" => [{ 'title' => 'Draft 151cm' }, { 'title' => 'Element 155cm' }] },
partials: {
'product' => "Product: {{ product.title }} ",
'product_alias' => "Product: {{ product.title }} ",
})
end
def test_render_tag_for_alias
Liquid::Template.file_system = StubFileSystem.new(
'product' => "Product: {{ product.title }} ",
'product_alias' => "Product: {{ product.title }} ",
)
assert_template_result("Product: Draft 151cm Product: Element 155cm ",
"{% render 'product_alias' for products as product %}",
{ "products" => [{ 'title' => 'Draft 151cm' }, { 'title' => 'Element 155cm' }] })
{ "products" => [{ 'title' => 'Draft 151cm' }, { 'title' => 'Element 155cm' }] },
partials: {
'product' => "Product: {{ product.title }} ",
'product_alias' => "Product: {{ product.title }} ",
})
end
def test_render_tag_for
Liquid::Template.file_system = StubFileSystem.new(
'product' => "Product: {{ product.title }} ",
'product_alias' => "Product: {{ product.title }} ",
)
assert_template_result("Product: Draft 151cm Product: Element 155cm ",
"{% render 'product' for products %}",
{ "products" => [{ 'title' => 'Draft 151cm' }, { 'title' => 'Element 155cm' }] })
{ "products" => [{ 'title' => 'Draft 151cm' }, { 'title' => 'Element 155cm' }] },
partials: {
'product' => "Product: {{ product.title }} ",
'product_alias' => "Product: {{ product.title }} ",
})
end
def test_render_tag_forloop
Liquid::Template.file_system = StubFileSystem.new(
'product' => "Product: {{ product.title }} {% if forloop.first %}first{% endif %} {% if forloop.last %}last{% endif %} index:{{ forloop.index }} ",
)
assert_template_result("Product: Draft 151cm first index:1 Product: Element 155cm last index:2 ",
"{% render 'product' for products %}",
{ "products" => [{ 'title' => 'Draft 151cm' }, { 'title' => 'Element 155cm' }] })
{ "products" => [{ 'title' => 'Draft 151cm' }, { 'title' => 'Element 155cm' }] },
partials: {
'product' => "Product: {{ product.title }} {% if forloop.first %}first{% endif %} {% if forloop.last %}last{% endif %} index:{{ forloop.index }} ",
})
end
def test_render_tag_for_drop
Liquid::Template.file_system = StubFileSystem.new(
'loop' => "{{ value.foo }}",
)
assert_template_result("123",
"{% render 'loop' for loop as value %}", { "loop" => TestEnumerable.new })
"{% render 'loop' for loop as value %}", { "loop" => TestEnumerable.new },
partials: {
'loop' => "{{ value.foo }}",
})
end
def test_render_tag_with_drop
Liquid::Template.file_system = StubFileSystem.new(
'loop' => "{{ value }}",
)
assert_template_result("TestEnumerable",
"{% render 'loop' with loop as value %}", { "loop" => TestEnumerable.new })
"{% render 'loop' with loop as value %}", { "loop" => TestEnumerable.new },
partials: {
'loop' => "{{ value }}",
})
end
end
+4
View File
@@ -56,6 +56,10 @@ module Minitest
assert_match(match, exception.message)
end
def assert_syntax_error(template, error_mode: nil)
assert_match_syntax_error("", template, error_mode: error_mode)
end
def assert_usage_increment(name, times: 1)
old_method = Liquid::Usage.method(:increment)
calls = 0