Skip to content

Commit 9cc19a4

Browse files
committed
update to latest spec tests
1 parent b2676e4 commit 9cc19a4

File tree

14 files changed

+1011
-19
lines changed

14 files changed

+1011
-19
lines changed

compiler/src/test/java/com/github/mustachejava/SpecTest.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import java.io.StringReader;
1313
import java.io.StringWriter;
1414
import java.util.HashMap;
15+
import java.util.List;
1516
import java.util.Map;
1617
import java.util.function.Function;
1718

@@ -101,7 +102,9 @@ public String apply(String input) {
101102
StringWriter writer = new StringWriter();
102103
String json = data.toString();
103104
if (json.startsWith("{")) {
104-
compile.execute(writer, new Object[]{new ObjectMapper().readValue(json, Map.class), functionMap.get(file)});
105+
compile.execute(writer, new Object[]{functionMap.get(file), new ObjectMapper().readValue(json, Map.class)});
106+
} else if (json.startsWith("[")) {
107+
compile.execute(writer, new Object[]{functionMap.get(file), new ObjectMapper().readValue(json, List.class)});
105108
} else {
106109
String s = new ObjectMapper().readValue(json, String.class);
107110
compile.execute(writer, new Object[]{functionMap.get(file), s});

compiler/src/test/resources/spec/specs/comments.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,18 @@
8989
},
9090
"template": "12345 {{! Comment Block! }} 67890",
9191
"expected": "12345 67890"
92+
},
93+
{
94+
"name": "Variable Name Collision",
95+
"desc": "Comments must never render, even if variable with same name exists.",
96+
"data": {
97+
"! comment": 1,
98+
"! comment ": 2,
99+
"!comment": 3,
100+
"comment": 4
101+
},
102+
"template": "comments never show: >{{! comment }}<",
103+
"expected": "comments never show: ><"
92104
}
93105
]
94106
}

compiler/src/test/resources/spec/specs/comments.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,3 +101,9 @@ tests:
101101
data: { }
102102
template: '12345 {{! Comment Block! }} 67890'
103103
expected: '12345 67890'
104+
105+
- name: Variable Name Collision
106+
desc: Comments must never render, even if variable with same name exists.
107+
data: { '! comment': 1, '! comment ': 2, '!comment': 3, 'comment': 4}
108+
template: 'comments never show: >{{! comment }}<'
109+
expected: 'comments never show: ><'

compiler/src/test/resources/spec/specs/interpolation.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,12 @@ tests:
4141
expected: |
4242
Hello, world!
4343
44+
- name: No Re-interpolation
45+
desc: Interpolated tag output should not be re-interpolated.
46+
data: { template: '{{planet}}', planet: 'Earth' }
47+
template: '{{template}}: {{planet}}'
48+
expected: '{{planet}}: Earth'
49+
4450
- name: HTML Escaping
4551
desc: Basic interpolation should be HTML escaped.
4652
data: { forbidden: '& " < >' }

compiler/src/test/resources/spec/specs/partials.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,20 @@
5555
},
5656
"expected": "X<Y<>>"
5757
},
58+
{
59+
"name": "Nested",
60+
"desc": "The greater-than operator should work from within partials.",
61+
"data": {
62+
"a": "hello",
63+
"b": "world"
64+
},
65+
"template": "{{>outer}}",
66+
"partials": {
67+
"outer": "*{{a}} {{>inner}}*",
68+
"inner": "{{b}}!"
69+
},
70+
"expected": "*hello world!*"
71+
},
5872
{
5973
"name": "Surrounding Whitespace",
6074
"desc": "The greater-than operator should not alter surrounding whitespace.",

compiler/src/test/resources/spec/specs/partials.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,13 @@ tests:
4242
partials: { node: '{{content}}<{{#nodes}}{{>node}}{{/nodes}}>' }
4343
expected: 'X<Y<>>'
4444

45+
- name: Nested
46+
desc: The greater-than operator should work from within partials.
47+
data: { a: "hello", b: "world" }
48+
template: '{{>outer}}'
49+
partials: { outer: '*{{a}} {{>inner}}*', inner: '{{b}}!' }
50+
expected: '*hello world!*'
51+
4552
# Whitespace Sensitivity
4653

4754
- name: Surrounding Whitespace

compiler/src/test/resources/spec/specs/sections.json

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"__ATTN__": "Do not edit this file; changes belong in the appropriate YAML file.",
3-
"overview": "Section tags and End Section tags are used in combination to wrap a section\nof the template for iteration\n\nThese tags' content MUST be a non-whitespace character sequence NOT\ncontaining the current closing delimiter; each Section tag MUST be followed\nby an End Section tag with the same content within the same section.\n\nThis tag's content names the data to replace the tag. Name resolution is as\nfollows:\n 1) Split the name on periods; the first part is the name to resolve, any\n remaining parts should be retained.\n 2) Walk the context stack from top to bottom, finding the first context\n that is a) a hash containing the name as a key OR b) an object responding\n to a method with the given name.\n 3) If the context is a hash, the data is the value associated with the\n name.\n 4) If the context is an object and the method with the given name has an\n arity of 1, the method SHOULD be called with a String containing the\n unprocessed contents of the sections; the data is the value returned.\n 5) Otherwise, the data is the value returned by calling the method with\n the given name.\n 6) If any name parts were retained in step 1, each should be resolved\n against a context stack containing only the result from the former\n resolution. If any part fails resolution, the result should be considered\n falsey, and should interpolate as the empty string.\nIf the data is not of a list type, it is coerced into a list as follows: if\nthe data is truthy (e.g. `!!data == true`), use a single-element list\ncontaining the data, otherwise use an empty list.\n\nFor each element in the data list, the element MUST be pushed onto the\ncontext stack, the section MUST be rendered, and the element MUST be popped\noff the context stack.\n\nSection and End Section tags SHOULD be treated as standalone when\nappropriate.\n",
3+
"overview": "Section tags and End Section tags are used in combination to wrap a section\nof the template for iteration.\n\nThese tags' content MUST be a non-whitespace character sequence NOT\ncontaining the current closing delimiter; each Section tag MUST be followed\nby an End Section tag with the same content within the same section.\n\nThis tag's content names the data to replace the tag. Name resolution is as\nfollows:\n 1) If the name is a single period (.), the data is the item currently\n sitting atop the context stack. Skip the rest of these steps.\n 2) Split the name on periods; the first part is the name to resolve, any\n remaining parts should be retained.\n 3) Walk the context stack from top to bottom, finding the first context\n that is a) a hash containing the name as a key OR b) an object responding\n to a method with the given name.\n 4) If the context is a hash, the data is the value associated with the\n name.\n 5) If the context is an object and the method with the given name has an\n arity of 1, the method SHOULD be called with a String containing the\n unprocessed contents of the sections; the data is the value returned.\n 6) Otherwise, the data is the value returned by calling the method with\n the given name.\n 7) If any name parts were retained in step 1, each should be resolved\n against a context stack containing only the result from the former\n resolution. If any part fails resolution, the result should be considered\n falsey, and should interpolate as the empty string.\n\nIf the data is not of a list type, it is coerced into a list as follows: if\nthe data is truthy (e.g. `!!data == true`), use a single-element list\ncontaining the data, otherwise use an empty list.\n\nFor each element in the data list, the element MUST be pushed onto the\ncontext stack, the section MUST be rendered, and the element MUST be popped\noff the context stack.\n\nSection and End Section tags SHOULD be treated as standalone when\nappropriate.\n",
44
"tests": [
55
{
66
"name": "Truthy",
@@ -246,6 +246,62 @@
246246
"template": "\"{{#list}}({{#.}}{{.}}{{/.}}){{/list}}\"",
247247
"expected": "\"(123)(abc)\""
248248
},
249+
{
250+
"name": "Implicit Iterator - HTML Escaping",
251+
"desc": "Implicit iterators with basic interpolation should be HTML escaped.",
252+
"data": {
253+
"list": [
254+
"&",
255+
"\"",
256+
"<",
257+
">"
258+
]
259+
},
260+
"template": "\"{{#list}}({{.}}){{/list}}\"",
261+
"expected": "\"(&amp;)(&quot;)(&lt;)(&gt;)\""
262+
},
263+
{
264+
"name": "Implicit Iterator - Triple mustache",
265+
"desc": "Implicit iterators in triple mustache should interpolate without HTML escaping.",
266+
"data": {
267+
"list": [
268+
"&",
269+
"\"",
270+
"<",
271+
">"
272+
]
273+
},
274+
"template": "\"{{#list}}({{{.}}}){{/list}}\"",
275+
"expected": "\"(&)(\")(<)(>)\""
276+
},
277+
{
278+
"name": "Implicit Iterator - Ampersand",
279+
"desc": "Implicit iterators in an Ampersand tag should interpolate without HTML escaping.",
280+
"data": {
281+
"list": [
282+
"&",
283+
"\"",
284+
"<",
285+
">"
286+
]
287+
},
288+
"template": "\"{{#list}}({{&.}}){{/list}}\"",
289+
"expected": "\"(&)(\")(<)(>)\""
290+
},
291+
{
292+
"name": "Implicit Iterator - Root-level",
293+
"desc": "Implicit iterators should work on root-level lists.",
294+
"data": [
295+
{
296+
"value": "a"
297+
},
298+
{
299+
"value": "b"
300+
}
301+
],
302+
"template": "\"{{#.}}({{value}}){{/.}}\"",
303+
"expected": "\"(a)(b)\""
304+
},
249305
{
250306
"name": "Dotted Names - Truthy",
251307
"desc": "Dotted names should be valid for Section tags.",

compiler/src/test/resources/spec/specs/sections.yml

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,32 @@
11
overview: |
22
Section tags and End Section tags are used in combination to wrap a section
3-
of the template for iteration
3+
of the template for iteration.
44
55
These tags' content MUST be a non-whitespace character sequence NOT
66
containing the current closing delimiter; each Section tag MUST be followed
77
by an End Section tag with the same content within the same section.
88
99
This tag's content names the data to replace the tag. Name resolution is as
1010
follows:
11-
1) Split the name on periods; the first part is the name to resolve, any
11+
1) If the name is a single period (.), the data is the item currently
12+
sitting atop the context stack. Skip the rest of these steps.
13+
2) Split the name on periods; the first part is the name to resolve, any
1214
remaining parts should be retained.
13-
2) Walk the context stack from top to bottom, finding the first context
15+
3) Walk the context stack from top to bottom, finding the first context
1416
that is a) a hash containing the name as a key OR b) an object responding
1517
to a method with the given name.
16-
3) If the context is a hash, the data is the value associated with the
18+
4) If the context is a hash, the data is the value associated with the
1719
name.
18-
4) If the context is an object and the method with the given name has an
20+
5) If the context is an object and the method with the given name has an
1921
arity of 1, the method SHOULD be called with a String containing the
2022
unprocessed contents of the sections; the data is the value returned.
21-
5) Otherwise, the data is the value returned by calling the method with
23+
6) Otherwise, the data is the value returned by calling the method with
2224
the given name.
23-
6) If any name parts were retained in step 1, each should be resolved
25+
7) If any name parts were retained in step 1, each should be resolved
2426
against a context stack containing only the result from the former
2527
resolution. If any part fails resolution, the result should be considered
2628
falsey, and should interpolate as the empty string.
29+
2730
If the data is not of a list type, it is coerced into a list as follows: if
2831
the data is truthy (e.g. `!!data == true`), use a single-element list
2932
containing the data, otherwise use an empty list.
@@ -206,6 +209,33 @@ tests:
206209
template: '"{{#list}}({{#.}}{{.}}{{/.}}){{/list}}"'
207210
expected: '"(123)(abc)"'
208211

212+
- name: Implicit Iterator - HTML Escaping
213+
desc: Implicit iterators with basic interpolation should be HTML escaped.
214+
data:
215+
list: [ '&', '"', '<', '>' ]
216+
template: '"{{#list}}({{.}}){{/list}}"'
217+
expected: '"(&amp;)(&quot;)(&lt;)(&gt;)"'
218+
219+
- name: Implicit Iterator - Triple mustache
220+
desc: Implicit iterators in triple mustache should interpolate without HTML escaping.
221+
data:
222+
list: [ '&', '"', '<', '>' ]
223+
template: '"{{#list}}({{{.}}}){{/list}}"'
224+
expected: '"(&)(")(<)(>)"'
225+
226+
- name: Implicit Iterator - Ampersand
227+
desc: Implicit iterators in an Ampersand tag should interpolate without HTML escaping.
228+
data:
229+
list: [ '&', '"', '<', '>' ]
230+
template: '"{{#list}}({{&.}}){{/list}}"'
231+
expected: '"(&)(")(<)(>)"'
232+
233+
- name: Implicit Iterator - Root-level
234+
desc: Implicit iterators should work on root-level lists.
235+
data: [ { value: 'a' }, { value: 'b' } ]
236+
template: '"{{#.}}({{value}}){{/.}}"'
237+
expected: '"(a)(b)"'
238+
209239
# Dotted Names
210240

211241
- name: Dotted Names - Truthy

0 commit comments

Comments
 (0)