From c306ed9f26e3b0dac825c3f3dd328db1edfd8af7 Mon Sep 17 00:00:00 2001 From: James Prior Date: Mon, 16 Jan 2023 07:55:11 +0000 Subject: [PATCH] Update golden browser tests [skip ci]. --- CHANGELOG.md | 2 +- tests/browser/test.golden.js | 1163 +++++++++++++++++++++++++++++++--- 2 files changed, 1082 insertions(+), 83 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a620d492..1feec3da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ **Fixes** - Fixed the string representation of variable paths that contain bracketed string elements with a dot. Previously `foo["x.y"].bar` would be represented as `foo.x.y.bar`. Now we retain the quoted property name `foo["x.y"].bar`. It is this string representation that is exposed in the results of `Template.analyze()`. See [#9](https://github.com/jg-rp/liquidscript/issues/9). -- Fixed named `{% cycle %}` tag behavior. See [Python Liquid/#43](https://github.com/jg-rp/liquid/issues/43). +- Fixed `{% cycle %}` tag behavior when given a cycle group name. See [Python Liquid/#43](https://github.com/jg-rp/liquid/issues/43). - Fixed the `round` filter when given non-integer arguments. See [Shopify/liquid#1590](https://github.com/Shopify/liquid/issues/1590). - Allow string literals to be used as a `{% for %}` tag iterable. See [Python Liquid/#102](https://github.com/jg-rp/liquid/issues/102). diff --git a/tests/browser/test.golden.js b/tests/browser/test.golden.js index b1152ac4..421f4912 100644 --- a/tests/browser/test.golden.js +++ b/tests/browser/test.golden.js @@ -1,5 +1,5 @@ const data = { - version: "0.7.0", + version: "0.14.0", test_groups: [ { name: "liquid.golden.abs_filter", @@ -803,6 +803,29 @@ const data = { error: false, strict: false, }, + { + name: "comma string literal", + template: + "{% case foo %}{% when 'foo' %}bar{% when ',' %}comma{% endcase %}", + want: "comma", + context: { + foo: ",", + }, + partials: {}, + error: false, + strict: false, + }, + { + name: "empty when tag", + template: "{% case foo %}{% when %}bar{% endcase %}", + want: "", + context: { + foo: "bar", + }, + partials: {}, + error: true, + strict: false, + }, { name: "evaluate multiple matching blocks", template: @@ -816,6 +839,30 @@ const data = { error: false, strict: false, }, + { + name: "mix or and comma separated when expression", + template: + "{% case title %}{% when 'foo' %}foo{% when 'bar' or 'Hello', 'Hello' %}bar{% endcase %}", + want: "barbar", + context: { + title: "Hello", + }, + partials: {}, + error: false, + strict: false, + }, + { + name: "mix or and comma separated when expression", + template: + "{% case title %}{% when 'foo' %}foo{% when 'bar' or 'Hello', 'Hello' %}bar{% endcase %}", + want: "barbar", + context: { + title: "Hello", + }, + partials: {}, + error: false, + strict: false, + }, { name: "name not in scope", template: @@ -860,6 +907,18 @@ const data = { error: false, strict: false, }, + { + name: "or separated when expression", + template: + "{% case title %}{% when 'foo' %}foo{% when 'bar' or 'Hello' %}bar{% endcase %}", + want: "bar", + context: { + title: "Hello", + }, + partials: {}, + error: false, + strict: false, + }, { name: "simple case/when", template: @@ -885,6 +944,18 @@ const data = { error: false, strict: false, }, + { + name: "unexpected when token", + template: + "{% case title %}{% when 'foo' %}foo{% when 'bar' and 'Hello', 'Hello' %}bar{% endcase %}", + want: "", + context: { + title: "Hello", + }, + partials: {}, + error: false, + strict: false, + }, { name: "whitespace", template: @@ -1277,6 +1348,56 @@ const data = { error: false, strict: false, }, + { + name: "multiple undefined variable names", + template: + "{% cycle a: 1, 2, 3 %}{% cycle b: 1, 2, 3 %}{% cycle a: 1, 2, 3 %}", + want: "123", + context: {}, + partials: {}, + error: false, + strict: false, + }, + { + name: "named with different items", + template: + "{% cycle 'a': 1, 2, 3 %}{% cycle 'a': 7, 8, 9 %}{% cycle 'a': 1, 2, 3 %}", + want: "183", + context: {}, + partials: {}, + error: false, + strict: false, + }, + { + name: "named with different number of arguments", + template: + "{% cycle a: '1', '2' %}{% cycle a: '1', '2', '3' %}{% cycle a: '1' %}", + want: "12", + context: {}, + partials: {}, + error: false, + strict: false, + }, + { + name: "named with growing number of arguments", + template: + "{% cycle a: '1' %}{% cycle a: '1', '2' %}{% cycle a: '1', '2', '3' %}", + want: "112", + context: {}, + partials: {}, + error: false, + strict: false, + }, + { + name: "named with shrinking number of arguments", + template: + "{% cycle a: '1', '2', '3' %}{% cycle a: '1', '2' %}{% cycle a: '1' %}", + want: "121", + context: {}, + partials: {}, + error: false, + strict: false, + }, { name: "no identifier", template: @@ -1287,6 +1408,16 @@ const data = { error: false, strict: false, }, + { + name: "undefined variable names mixed with no name", + template: + "{% cycle a: 1, 2, 3 %}{% cycle b: 1, 2, 3 %}{% cycle 1, 2, 3 %}", + want: "121", + context: {}, + partials: {}, + error: false, + strict: false, + }, { name: "variable name", template: @@ -1323,6 +1454,24 @@ const data = { error: true, strict: false, }, + { + name: "timestamp integer", + template: "{{ 1152098955 | date: '%m/%d/%Y' }}", + want: "07/05/2006", + context: {}, + partials: {}, + error: false, + strict: false, + }, + { + name: "timestamp string", + template: "{{ '1152098955' | date: '%m/%d/%Y' }}", + want: "07/05/2006", + context: {}, + partials: {}, + error: false, + strict: false, + }, { name: "too many arguments", template: "{{ 'March 14, 2016' | date: '%b %d, %y', 'foo' }}", @@ -1379,6 +1528,15 @@ const data = { { name: "liquid.golden.default_filter", tests: [ + { + name: "0.0 is not falsy", + template: '{{ 0.0 | default: "bar" }}', + want: "0.0", + context: {}, + partials: {}, + error: false, + strict: false, + }, { name: "allow false", template: "{{ false | default: 'bar', allow_false:true }}", @@ -1448,6 +1606,15 @@ const data = { error: false, strict: false, }, + { + name: "false keyword argument before positional", + template: '{{ false | default: allow_false: false, "bar" }}', + want: "bar", + context: {}, + partials: {}, + error: false, + strict: false, + }, { name: "missing argument", template: "{{ false | default }}", @@ -1512,6 +1679,15 @@ const data = { error: true, strict: false, }, + { + name: "true keyword argument before positional", + template: '{{ false | default: allow_false: true, "bar" }}', + want: "false", + context: {}, + partials: {}, + error: false, + strict: false, + }, { name: "undefined left value", template: '{{ nosuchthing | default: "bar" }}', @@ -1521,6 +1697,24 @@ const data = { error: false, strict: false, }, + { + name: "zero is not falsy", + template: '{{ 0 | default: "bar" }}', + want: "0", + context: {}, + partials: {}, + error: false, + strict: false, + }, + { + name: "zero is not falsy with allow_false", + template: '{{ 0 | default: "bar", allow_false: true }}', + want: "0", + context: {}, + partials: {}, + error: false, + strict: false, + }, ], }, { @@ -2262,6 +2456,16 @@ const data = { error: false, strict: false, }, + { + name: "comma separated arguments", + template: + "{% for i in (1..6), limit: 4, offset: 2 %}{{ i }} {% endfor %}", + want: "3 4 5 6 ", + context: {}, + partials: {}, + error: false, + strict: false, + }, { name: "continue", template: @@ -2605,6 +2809,35 @@ const data = { error: false, strict: false, }, + { + name: "limit is a non-number string", + template: "{% for i in (1..4) limit: 'foo' %}{{ i }} {% endfor %}", + want: "", + context: {}, + partials: {}, + error: true, + strict: false, + }, + { + name: "limit is a string", + template: "{% for i in (1..4) limit: '2' %}{{ i }} {% endfor %}", + want: "1 2 ", + context: {}, + partials: {}, + error: false, + strict: false, + }, + { + name: "limit is not a string or number", + template: "{% for i in (1..4) limit: foo %}{{ i }} {% endfor %}", + want: "", + context: { + foo: [1, 2, 3], + }, + partials: {}, + error: true, + strict: false, + }, { name: "lookup a filter from an outer context", template: @@ -2619,6 +2852,26 @@ const data = { error: false, strict: false, }, + { + name: "loop over a string literal", + template: "{% for i in 'hello' %}{{ i }} {% endfor %}", + want: "hello ", + context: {}, + partials: {}, + error: false, + strict: false, + }, + { + name: "loop over a string variable", + template: "{% for i in foo %}{{ i }} {% endfor %}", + want: "hello ", + context: { + foo: "hello", + }, + partials: {}, + error: false, + strict: false, + }, { name: "loop over an array in reverse", template: @@ -2793,6 +3046,35 @@ const data = { error: false, strict: false, }, + { + name: "offset is a non-number string", + template: "{% for i in (1..4) offset: 'foo' %}{{ i }} {% endfor %}", + want: "", + context: {}, + partials: {}, + error: true, + strict: false, + }, + { + name: "offset is a string", + template: "{% for i in (1..4) offset: '2' %}{{ i }} {% endfor %}", + want: "3 4 ", + context: {}, + partials: {}, + error: false, + strict: false, + }, + { + name: "offset is not a string or number", + template: "{% for i in (1..4) offset: foo %}{{ i }} {% endfor %}", + want: "", + context: { + foo: [1, 2, 3], + }, + partials: {}, + error: true, + strict: false, + }, { name: "parent's parentloop", template: @@ -2838,6 +3120,24 @@ const data = { error: false, strict: false, }, + { + name: "range start and stop are the same", + template: "{% for i in (1..1) %}{{ i }} {% endfor %}", + want: "1 ", + context: {}, + partials: {}, + error: false, + strict: false, + }, + { + name: "range start and stop are zero", + template: "{% for i in (0..0) %}{{ i }} {% endfor %}", + want: "0 ", + context: {}, + partials: {}, + error: false, + strict: false, + }, { name: "share outer scope", template: @@ -2885,42 +3185,364 @@ const data = { error: false, strict: false, }, + { + name: "some comma separated arguments", + template: + "{% for i in (1..6) limit: 4, offset: 2, %}{{ i }} {% endfor %}", + want: "3 4 5 6 ", + context: {}, + partials: {}, + error: false, + strict: false, + }, ], }, { - name: "liquid.golden.if_tag", + name: "liquid.golden.identifiers", tests: [ { - name: "alternate not equal condition", - template: "{% if product.title <> 'foo' %}baz{% endif %}", - want: "", + name: "ascii lowercase", + template: "{% assign foo = 'hello' %}{{ foo }} {{ bar }}", + want: "hello goodbye", context: { - product: { - title: "foo", - }, + bar: "goodbye", }, partials: {}, error: false, - strict: false, + strict: true, }, { - name: "blocks that contain only whitespace and comments are not rendered", - template: - "{% if true %} {% comment %} this is blank {% endcomment %} {% endif %}", - want: "", - context: {}, + name: "ascii uppercase", + template: "{% assign FOO = 'hello' %}{{ FOO }} {{ BAR }}", + want: "hello goodbye", + context: { + BAR: "goodbye", + }, partials: {}, error: false, - strict: false, + strict: true, }, { - name: "blocks that contain only whitespace are not rendered", - template: "{% if true %} {% elsif false %} {% else %} {% endif %}", - want: "", - context: {}, + name: "at sign", + template: "{{ @foo }}", + want: "hello", + context: { + "@foo": "hello", + }, partials: {}, - error: false, - strict: false, + error: true, + strict: true, + }, + { + name: "capture ascii lowercase", + template: "{% capture foo %}hello{% endcapture %}{{ foo }}", + want: "hello", + context: {}, + partials: {}, + error: false, + strict: true, + }, + { + name: "capture ascii uppercase", + template: "{% capture FOO %}hello{% endcapture %}{{ FOO }}", + want: "hello", + context: {}, + partials: {}, + error: false, + strict: true, + }, + { + name: "capture digits", + template: "{% capture foo1 %}hello{% endcapture %}{{ foo1 }}", + want: "hello", + context: {}, + partials: {}, + error: false, + strict: true, + }, + { + name: "capture hyphens", + template: + "{% capture foo-a %}hello {{ bar-b }}{% endcapture %}{{ foo-a }}", + want: "hello goodbye", + context: { + "bar-b": "goodbye", + }, + partials: {}, + error: false, + strict: true, + }, + { + name: "capture leading hyphen", + template: + "{% capture -foo %}hello {{ -bar }}{% endcapture %}{{ -foo }}", + want: "hello goodbye", + context: { + "-bar": "goodbye", + }, + partials: {}, + error: true, + strict: true, + }, + { + name: "capture leading underscore", + template: + "{% capture _foo %}hello {{ _bar }}{% endcapture %}{{ _foo }}", + want: "hello goodbye", + context: { + _bar: "goodbye", + }, + partials: {}, + error: false, + strict: true, + }, + { + name: "capture only digits", + template: "{% capture 123 %}hello{% endcapture %}{{ 123 }}", + want: "123", + context: {}, + partials: {}, + error: false, + strict: true, + }, + { + name: "capture only underscore", + template: "{% capture _ %}hello {{ __ }}{% endcapture %}{{ _ }}", + want: "hello goodbye", + context: { + __: "goodbye", + }, + partials: {}, + error: false, + strict: true, + }, + { + name: "capture underscore", + template: + "{% capture foo_a %}hello {{ bar_b }}{% endcapture %}{{ foo_a }}", + want: "hello goodbye", + context: { + bar_b: "goodbye", + }, + partials: {}, + error: false, + strict: true, + }, + { + name: "decrement with a hyphen", + template: "{% decrement f-oo %}{% decrement f-oo %}", + want: "-1-2", + context: {}, + partials: {}, + error: false, + strict: true, + }, + { + name: "digits", + template: "{% assign foo1 = 'hello' %}{{ foo1 }} {{ bar2 }}", + want: "hello goodbye", + context: { + bar2: "goodbye", + }, + partials: {}, + error: false, + strict: true, + }, + { + name: "hyphen in for loop target", + template: "{% for x in f-oo %}{{ x }}{% endfor %}", + want: "123", + context: { + "f-oo": [1, 2, 3], + }, + partials: {}, + error: false, + strict: true, + }, + { + name: "hyphen in for loop variable", + template: "{% for x-y in foo %}{{ x-y }}{% endfor %}", + want: "123", + context: { + foo: [1, 2, 3], + }, + partials: {}, + error: false, + strict: true, + }, + { + name: "hyphens", + template: "{% assign foo-a = 'hello' %}{{ foo-a }} {{ bar-b }}", + want: "hello goodbye", + context: { + "bar-b": "goodbye", + }, + partials: {}, + error: false, + strict: true, + }, + { + name: "increment with a hyphen", + template: "{% increment f-oo %}{% increment f-oo %}", + want: "01", + context: {}, + partials: {}, + error: false, + strict: true, + }, + { + name: "leading hyphen", + template: "{% assign -foo = 'hello' %}{{ -foo }} {{ -bar }}", + want: "hello goodbye", + context: { + "-bar": "goodbye", + }, + partials: {}, + error: true, + strict: true, + }, + { + name: "leading hyphen in for loop target", + template: "{% for x in -foo %}{{ x }}{% endfor %}", + want: "123", + context: { + "-foo": [1, 2, 3], + }, + partials: {}, + error: true, + strict: true, + }, + { + name: "leading underscore", + template: "{% assign _foo = 'hello' %}{{ _foo }} {{ _bar }}", + want: "hello goodbye", + context: { + _bar: "goodbye", + }, + partials: {}, + error: false, + strict: true, + }, + { + name: "only digits", + template: "{% assign 123 = 'hello' %}{{ 123 }} {{ 456 }}", + want: "123 456", + context: { + 456: "goodbye", + }, + partials: {}, + error: false, + strict: true, + }, + { + name: "only underscore", + template: "{% assign _ = 'hello' %}{{ _ }} {{ __ }}", + want: "hello goodbye", + context: { + __: "goodbye", + }, + partials: {}, + error: false, + strict: true, + }, + { + name: "trailing question mark assign", + template: "{% assign foo? = 'hello' %}{{ foo? }}", + want: "hello", + context: {}, + partials: {}, + error: true, + strict: true, + }, + { + name: "trailing question mark in for loop target", + template: "{% for x in foo? %}{{ x }}{% endfor %}", + want: "123", + context: { + "foo?": [1, 2, 3], + }, + partials: {}, + error: false, + strict: true, + }, + { + name: "trailing question mark in for loop variable", + template: "{% for x? in foo %}{{ x? }}{% endfor %}", + want: "123", + context: { + foo: [1, 2, 3], + }, + partials: {}, + error: false, + strict: true, + }, + { + name: "trailing question mark output", + template: "{{ bar? }}", + want: "goodbye", + context: { + "bar?": "goodbye", + }, + partials: {}, + error: false, + strict: true, + }, + { + name: "underscore", + template: "{% assign foo_a = 'hello' %}{{ foo_a }} {{ bar_b }}", + want: "hello goodbye", + context: { + bar_b: "goodbye", + }, + partials: {}, + error: false, + strict: true, + }, + ], + }, + { + name: "liquid.golden.if_tag", + tests: [ + { + name: "0.0 is truthy", + template: "{% if 0.0 %}Hello{% else %}Goodbye{% endif %}", + want: "Hello", + context: {}, + partials: {}, + error: false, + strict: false, + }, + { + name: "alternate not equal condition", + template: "{% if product.title <> 'foo' %}baz{% endif %}", + want: "", + context: { + product: { + title: "foo", + }, + }, + partials: {}, + error: false, + strict: false, + }, + { + name: "blocks that contain only whitespace and comments are not rendered", + template: + "{% if true %} {% comment %} this is blank {% endcomment %} {% endif %}", + want: "", + context: {}, + partials: {}, + error: false, + strict: false, + }, + { + name: "blocks that contain only whitespace are not rendered", + template: "{% if true %} {% elsif false %} {% else %} {% endif %}", + want: "", + context: {}, + partials: {}, + error: false, + strict: false, }, { name: "condition with conditional alternative", @@ -3083,6 +3705,15 @@ const data = { error: false, strict: false, }, + { + name: "one is not equal to true", + template: "{% if 1 == true %}Hello{% else %}Goodbye{% endif %}", + want: "Goodbye", + context: {}, + partials: {}, + error: false, + strict: false, + }, { name: "range equals range", template: @@ -3102,6 +3733,24 @@ const data = { error: false, strict: false, }, + { + name: "zero is not equal to false", + template: "{% if 0 == false %}Hello{% else %}Goodbye{% endif %}", + want: "Goodbye", + context: {}, + partials: {}, + error: false, + strict: false, + }, + { + name: "zero is truthy", + template: "{% if 0 %}Hello{% else %}Goodbye{% endif %}", + want: "Hello", + context: {}, + partials: {}, + error: false, + strict: false, + }, ], }, { @@ -3217,6 +3866,17 @@ const data = { error: false, strict: false, }, + { + name: "assign to a keyword argument", + template: "{% include 'product-args', foo: 'hello' %} {{ foo }}", + want: "hello hello goodbye", + context: {}, + partials: { + "product-args": "{{ foo }}{% assign foo = 'goodbye' %} {{ foo }}", + }, + error: false, + strict: false, + }, { name: "bound array variable", template: "{% include 'prod' for collection.products %}", @@ -3408,93 +4068,201 @@ const data = { template: "{% include 'product-args' foo: 'hello', bar: 'there' %}", want: "hello there", context: {}, - partials: { - "product-args": "{{ foo }} {{ bar }}", - }, + partials: { + "product-args": "{{ foo }} {{ bar }}", + }, + error: false, + strict: false, + }, + { + name: "string literal name", + template: "{% include 'product-hero' %}", + want: "foo\n- sports\n- garden\n", + context: { + product: { + title: "foo", + tags: ["sports", "garden"], + }, + }, + partials: { + "product-hero": + "{{ product.title }}\n{% for tag in product.tags %}- {{ tag }}\n{% endfor %}", + }, + error: false, + strict: false, + }, + { + name: "use globals from outer scope", + template: "{% include 'outer-scope' %}", + want: "Hello, Holly", + context: { + customer: { + first_name: "Holly", + }, + }, + partials: { + "outer-scope": "Hello, {{ customer.first_name }}", + }, + error: false, + strict: false, + }, + ], + }, + { + name: "liquid.golden.increment_tag", + tests: [ + { + name: "assign and increment", + template: + "{% assign foo = 5 %}{{ foo }} {% increment foo %} {% increment foo %} {{ foo }}", + want: "5 0 1 5", + context: {}, + partials: {}, + error: false, + strict: false, + }, + { + name: "incrementing counter renders before incrementing", + template: "{% increment foo %} {{ foo }}", + want: "0 1", + context: {}, + partials: {}, + error: false, + strict: false, + }, + { + name: "multiple named counters", + template: + "{% increment foo %} {% increment bar %} {% increment foo %} {% increment bar %}", + want: "0 0 1 1", + context: {}, + partials: {}, + error: false, + strict: false, + }, + { + name: "named counter", + template: + "{% increment foo %} {% increment foo %} {% increment foo %}", + want: "0 1 2", + context: {}, + partials: {}, + error: false, + strict: false, + }, + { + name: "named counters are in scope for subsequent expressions", + template: + "{% increment foo %} {% increment foo %} {% if foo > 0 %}{{ foo }}{% endif %}", + want: "0 1 2", + context: {}, + partials: {}, + error: false, + strict: false, + }, + ], + }, + { + name: "liquid.golden.inline_comment_tag", + tests: [ + { + name: "can't comment tags", + template: "{%- # {% echo 'hello world' %} -%}", + want: " -%}", + context: {}, + partials: {}, + error: false, + strict: false, + }, + { + name: "empty", + template: "{%#%}", + want: "", + context: {}, + partials: {}, + error: false, + strict: false, + }, + { + name: "enforce leading hash", + template: + "{%-\n # spread inline comments\n over multiple lines\n-%}", + want: "", + context: {}, + partials: {}, + error: true, + strict: false, + }, + { + name: "liquid tag", + template: + "{% liquid \n # first comment line\n # second comment line\n\n # another comment line\n echo 'Hello '\n\n # more comments\n echo 'goodbye'\n-%}", + want: "Hello goodbye", + context: {}, + partials: {}, error: false, strict: false, }, { - name: "string literal name", - template: "{% include 'product-hero' %}", - want: "foo\n- sports\n- garden\n", - context: { - product: { - title: "foo", - tags: ["sports", "garden"], - }, - }, - partials: { - "product-hero": - "{{ product.title }}\n{% for tag in product.tags %}- {{ tag }}\n{% endfor %}", - }, + name: "lots of hashes in a liquid tag", + template: + "{% liquid\n ##########################\n # spread inline comments #\n ##########################\n-%}", + want: "", + context: {}, + partials: {}, error: false, strict: false, }, { - name: "use globals from outer scope", - template: "{% include 'outer-scope' %}", - want: "Hello, Holly", - context: { - customer: { - first_name: "Holly", - }, - }, - partials: { - "outer-scope": "Hello, {{ customer.first_name }}", - }, + name: "multiple lines", + template: + "{%-\n # spread inline comments\n # over multiple lines\n-%}", + want: "", + context: {}, + partials: {}, error: false, strict: false, }, - ], - }, - { - name: "liquid.golden.increment_tag", - tests: [ { - name: "assign and increment", - template: - "{% assign foo = 5 %}{{ foo }} {% increment foo %} {% increment foo %} {{ foo }}", - want: "5 0 1 5", + name: "no padding after the hash", + template: "{%#some comment %}", + want: "", context: {}, partials: {}, error: false, strict: false, }, { - name: "incrementing counter renders before incrementing", - template: "{% increment foo %} {{ foo }}", - want: "0 1", + name: "no whitespace control no padding", + template: "{%# some comment %}", + want: "", context: {}, partials: {}, error: false, strict: false, }, { - name: "multiple named counters", - template: - "{% increment foo %} {% increment bar %} {% increment foo %} {% increment bar %}", - want: "0 0 1 1", + name: "no whitespace control with padding", + template: "{% # some comment %}", + want: "", context: {}, partials: {}, error: false, strict: false, }, { - name: "named counter", - template: - "{% increment foo %} {% increment foo %} {% increment foo %}", - want: "0 1 2", + name: "with whitespace control and padding", + template: "{%- # some comment -%}", + want: "", context: {}, partials: {}, error: false, strict: false, }, { - name: "named counters are in scope for subsequent expressions", - template: - "{% increment foo %} {% increment foo %} {% if foo > 0 %}{{ foo }}{% endif %}", - want: "0 1 2", + name: "with whitespace control no padding", + template: "{%-# some comment -%}", + want: "", context: {}, partials: {}, error: false, @@ -5117,6 +5885,17 @@ const data = { { name: "liquid.golden.render_tag", tests: [ + { + name: "assign to keyword argument", + template: "{% render 'product-args', foo: 'hello' %}{{ foo }}", + want: "hello goodbye", + context: {}, + partials: { + "product-args": "{{ foo }}{% assign foo='goodbye' %} {{ foo }}", + }, + error: false, + strict: false, + }, { name: "assigned variables do not leak into outer scope", template: @@ -5729,6 +6508,60 @@ const data = { { name: "liquid.golden.round_filter", tests: [ + { + name: "argument is a float", + template: "{{ 5.666 | round: 1.2 }}", + want: "5.7", + context: {}, + partials: {}, + error: false, + strict: false, + }, + { + name: "argument is a negative", + template: "{{ 5.666 | round: -2 }}", + want: "0", + context: {}, + partials: {}, + error: false, + strict: false, + }, + { + name: "argument is a string", + template: "{{ 5.666 | round: 'foo' }}", + want: "6", + context: {}, + partials: {}, + error: false, + strict: false, + }, + { + name: "argument is a string representation of an integer", + template: "{{ 5.666 | round: '1' }}", + want: "5.7", + context: {}, + partials: {}, + error: false, + strict: false, + }, + { + name: "argument is a string representation of zero", + template: "{{ 5.666 | round: '1' }}", + want: "5.7", + context: {}, + partials: {}, + error: false, + strict: false, + }, + { + name: "argument is a zero", + template: "{{ 5.666 | round: 0 }}", + want: "6", + context: {}, + partials: {}, + error: false, + strict: false, + }, { name: "decimal places", template: '{{ "5.666666" | round: 2 }}', @@ -5795,7 +6628,7 @@ const data = { { name: "undefined argument", template: "{{ 5.666 | round: nosuchthing }}", - want: "6.0", + want: "6", context: {}, partials: {}, error: false, @@ -6230,6 +7063,17 @@ const data = { error: false, strict: false, }, + { + name: "incompatible types", + template: "{{ a | sort }}", + want: "", + context: { + a: [[], {}, 1, "4"], + }, + partials: {}, + error: true, + strict: false, + }, { name: "left value is not an array", template: "{{ a | sort | join: '#' }}", @@ -6890,6 +7734,56 @@ const data = { { name: "liquid.golden.tablerow_tag", tests: [ + { + name: "cols is a float", + template: + "{% tablerow i in (1..4) cols:2.6 %}{{ i }} {{ tablerowloop.col_first }}{% endtablerow %}", + want: '\n1 true2 false\n3 true4 false\n', + context: {}, + partials: {}, + error: false, + strict: false, + }, + { + name: "cols is a string", + template: + "{% tablerow i in (1..4) cols:'2' %}{{ i }} {{ tablerowloop.col_first }}{% endtablerow %}", + want: '\n1 true2 false\n3 true4 false\n', + context: {}, + partials: {}, + error: false, + strict: false, + }, + { + name: "limit is a string", + template: + "{% tablerow i in (1..4) limit:'2' %}{{ i }} {{ tablerowloop.col_first }}{% endtablerow %}", + want: '\n1 true2 false\n', + context: {}, + partials: {}, + error: false, + strict: false, + }, + { + name: "no cols param", + template: + "{% tablerow i in (1..2) %}\ncol: {{ tablerowloop.col }}\ncol0: {{ tablerowloop.col0 }}\ncol_first: {{ tablerowloop.col_first }}\ncol_last: {{ tablerowloop.col_last }}\nfirst: {{ tablerowloop.first }}\nindex: {{ tablerowloop.index }}\nindex0: {{ tablerowloop.index0 }}\nlast: {{ tablerowloop.last }}\nlength: {{ tablerowloop.length }}\nrindex: {{ tablerowloop.rindex }}\nrindex0: {{ tablerowloop.rindex0 }}\nrow: {{ tablerowloop.row }}\n{% endtablerow %}", + want: '\n\ncol: 1\ncol0: 0\ncol_first: true\ncol_last: false\nfirst: true\nindex: 1\nindex0: 0\nlast: false\nlength: 2\nrindex: 2\nrindex0: 1\nrow: 1\n\ncol: 2\ncol0: 1\ncol_first: false\ncol_last: true\nfirst: false\nindex: 2\nindex0: 1\nlast: true\nlength: 2\nrindex: 1\nrindex0: 0\nrow: 1\n\n', + context: {}, + partials: {}, + error: false, + strict: false, + }, + { + name: "offset is a string", + template: + "{% tablerow i in (1..4) offset:'2' %}{{ i }} {{ tablerowloop.col_first }}{% endtablerow %}", + want: '\n3 true4 false\n', + context: {}, + partials: {}, + error: false, + strict: false, + }, { name: "one row", template: @@ -6942,6 +7836,16 @@ const data = { error: false, strict: false, }, + { + name: "two column odd range row numbers", + template: + "{% tablerow i in (1..5) cols:2 %}{{ i }} {{ tablerowloop.row }}{% endtablerow %}", + want: '\n1 12 1\n3 24 2\n5 3\n', + context: {}, + partials: {}, + error: false, + strict: false, + }, { name: "two column range", template: @@ -7156,6 +8060,15 @@ const data = { { name: "liquid.golden.truncatewords_filter", tests: [ + { + name: "all whitespace is clobbered", + template: '{{ " one two three four " | truncatewords: 2 }}', + want: "one two...", + context: {}, + partials: {}, + error: false, + strict: false, + }, { name: "custom end", template: @@ -7295,15 +8208,6 @@ const data = { error: false, strict: false, }, - { - name: "very big argument", - template: '{{ "" | truncatewords: 100000000000000 }}', - want: "", - context: {}, - partials: {}, - error: false, - strict: false, - }, ], }, { @@ -7500,6 +8404,35 @@ const data = { error: false, strict: false, }, + { + name: "one is not equal to true", + template: + "{% unless 1 == true %}Hello{% else %}Goodbye{% endunless %}", + want: "Hello", + context: {}, + partials: {}, + error: false, + strict: false, + }, + { + name: "zero is not equal to false", + template: + "{% unless 0 == false %}Hello{% else %}Goodbye{% endunless %}", + want: "Hello", + context: {}, + partials: {}, + error: false, + strict: false, + }, + { + name: "zero is truthy", + template: "{% unless 0 %}Hello{% else %}Goodbye{% endunless %}", + want: "Goodbye", + context: {}, + partials: {}, + error: false, + strict: false, + }, ], }, { @@ -7778,6 +8711,28 @@ const data = { error: true, strict: false, }, + { + name: "second argument is undefined", + template: + "{% assign x = a | where: 'title', nosuchthing %}{% for obj in x %}{% for i in obj %}({{ i[0] }},{{ i[1] }}){% endfor %}{% endfor %}", + want: "(title,foo)(title,bar)", + context: { + a: [ + { + title: "foo", + }, + { + title: "bar", + }, + { + title: null, + }, + ], + }, + partials: {}, + error: false, + strict: false, + }, { name: "too many arguments", template: "{{ a | where: 'title', 'foo', 'bar' }}", @@ -7799,6 +8754,50 @@ const data = { error: true, strict: false, }, + { + name: "value is explicit nil", + template: + "{% assign x = a | where: 'b', nil %}{% for obj in x %}{% for i in obj %}({{ i[0] }},{{ i[1] }}){% endfor %}{% endfor %}", + want: "(b,bar)", + context: { + a: [ + { + b: false, + }, + { + b: "bar", + }, + { + b: null, + }, + ], + }, + partials: {}, + error: false, + strict: false, + }, + { + name: "value is false", + template: + "{% assign x = a | where: 'b', false %}{% for obj in x %}{% for i in obj %}({{ i[0] }},{{ i[1] }}){% endfor %}{% endfor %}", + want: "(b,false)", + context: { + a: [ + { + b: false, + }, + { + b: "bar", + }, + { + b: null, + }, + ], + }, + partials: {}, + error: false, + strict: false, + }, ], }, {