Index: pkg/mustache/test/spec/sections.yml |
diff --git a/pkg/mustache/test/spec/sections.yml b/pkg/mustache/test/spec/sections.yml |
new file mode 100644 |
index 0000000000000000000000000000000000000000..f62d9cb30a989b4632c1b20bb30b2dc2b8c9742c |
--- /dev/null |
+++ b/pkg/mustache/test/spec/sections.yml |
@@ -0,0 +1,256 @@ |
+overview: | |
+ Section tags and End Section tags are used in combination to wrap a section |
+ of the template for iteration |
+ |
+ These tags' content MUST be a non-whitespace character sequence NOT |
+ containing the current closing delimiter; each Section tag MUST be followed |
+ by an End Section tag with the same content within the same section. |
+ |
+ This tag's content names the data to replace the tag. Name resolution is as |
+ follows: |
+ 1) Split the name on periods; the first part is the name to resolve, any |
+ remaining parts should be retained. |
+ 2) Walk the context stack from top to bottom, finding the first context |
+ that is a) a hash containing the name as a key OR b) an object responding |
+ to a method with the given name. |
+ 3) If the context is a hash, the data is the value associated with the |
+ name. |
+ 4) If the context is an object and the method with the given name has an |
+ arity of 1, the method SHOULD be called with a String containing the |
+ unprocessed contents of the sections; the data is the value returned. |
+ 5) Otherwise, the data is the value returned by calling the method with |
+ the given name. |
+ 6) If any name parts were retained in step 1, each should be resolved |
+ against a context stack containing only the result from the former |
+ resolution. If any part fails resolution, the result should be considered |
+ falsey, and should interpolate as the empty string. |
+ If the data is not of a list type, it is coerced into a list as follows: if |
+ the data is truthy (e.g. `!!data == true`), use a single-element list |
+ containing the data, otherwise use an empty list. |
+ |
+ For each element in the data list, the element MUST be pushed onto the |
+ context stack, the section MUST be rendered, and the element MUST be popped |
+ off the context stack. |
+ |
+ Section and End Section tags SHOULD be treated as standalone when |
+ appropriate. |
+tests: |
+ - name: Truthy |
+ desc: Truthy sections should have their contents rendered. |
+ data: { boolean: true } |
+ template: '"{{#boolean}}This should be rendered.{{/boolean}}"' |
+ expected: '"This should be rendered."' |
+ |
+ - name: Falsey |
+ desc: Falsey sections should have their contents omitted. |
+ data: { boolean: false } |
+ template: '"{{#boolean}}This should not be rendered.{{/boolean}}"' |
+ expected: '""' |
+ |
+ - name: Context |
+ desc: Objects and hashes should be pushed onto the context stack. |
+ data: { context: { name: 'Joe' } } |
+ template: '"{{#context}}Hi {{name}}.{{/context}}"' |
+ expected: '"Hi Joe."' |
+ |
+ - name: Deeply Nested Contexts |
+ desc: All elements on the context stack should be accessible. |
+ data: |
+ a: { one: 1 } |
+ b: { two: 2 } |
+ c: { three: 3 } |
+ d: { four: 4 } |
+ e: { five: 5 } |
+ template: | |
+ {{#a}} |
+ {{one}} |
+ {{#b}} |
+ {{one}}{{two}}{{one}} |
+ {{#c}} |
+ {{one}}{{two}}{{three}}{{two}}{{one}} |
+ {{#d}} |
+ {{one}}{{two}}{{three}}{{four}}{{three}}{{two}}{{one}} |
+ {{#e}} |
+ {{one}}{{two}}{{three}}{{four}}{{five}}{{four}}{{three}}{{two}}{{one}} |
+ {{/e}} |
+ {{one}}{{two}}{{three}}{{four}}{{three}}{{two}}{{one}} |
+ {{/d}} |
+ {{one}}{{two}}{{three}}{{two}}{{one}} |
+ {{/c}} |
+ {{one}}{{two}}{{one}} |
+ {{/b}} |
+ {{one}} |
+ {{/a}} |
+ expected: | |
+ 1 |
+ 121 |
+ 12321 |
+ 1234321 |
+ 123454321 |
+ 1234321 |
+ 12321 |
+ 121 |
+ 1 |
+ |
+ - name: List |
+ desc: Lists should be iterated; list items should visit the context stack. |
+ data: { list: [ { item: 1 }, { item: 2 }, { item: 3 } ] } |
+ template: '"{{#list}}{{item}}{{/list}}"' |
+ expected: '"123"' |
+ |
+ - name: Empty List |
+ desc: Empty lists should behave like falsey values. |
+ data: { list: [ ] } |
+ template: '"{{#list}}Yay lists!{{/list}}"' |
+ expected: '""' |
+ |
+ - name: Doubled |
+ desc: Multiple sections per template should be permitted. |
+ data: { bool: true, two: 'second' } |
+ template: | |
+ {{#bool}} |
+ * first |
+ {{/bool}} |
+ * {{two}} |
+ {{#bool}} |
+ * third |
+ {{/bool}} |
+ expected: | |
+ * first |
+ * second |
+ * third |
+ |
+ - name: Nested (Truthy) |
+ desc: Nested truthy sections should have their contents rendered. |
+ data: { bool: true } |
+ template: "| A {{#bool}}B {{#bool}}C{{/bool}} D{{/bool}} E |" |
+ expected: "| A B C D E |" |
+ |
+ - name: Nested (Falsey) |
+ desc: Nested falsey sections should be omitted. |
+ data: { bool: false } |
+ template: "| A {{#bool}}B {{#bool}}C{{/bool}} D{{/bool}} E |" |
+ expected: "| A E |" |
+ |
+ - name: Context Misses |
+ desc: Failed context lookups should be considered falsey. |
+ data: { } |
+ template: "[{{#missing}}Found key 'missing'!{{/missing}}]" |
+ expected: "[]" |
+ |
+ # Implicit Iterators |
+ |
+ - name: Implicit Iterator - String |
+ desc: Implicit iterators should directly interpolate strings. |
+ data: |
+ list: [ 'a', 'b', 'c', 'd', 'e' ] |
+ template: '"{{#list}}({{.}}){{/list}}"' |
+ expected: '"(a)(b)(c)(d)(e)"' |
+ |
+ - name: Implicit Iterator - Integer |
+ desc: Implicit iterators should cast integers to strings and interpolate. |
+ data: |
+ list: [ 1, 2, 3, 4, 5 ] |
+ template: '"{{#list}}({{.}}){{/list}}"' |
+ expected: '"(1)(2)(3)(4)(5)"' |
+ |
+ - name: Implicit Iterator - Decimal |
+ desc: Implicit iterators should cast decimals to strings and interpolate. |
+ data: |
+ list: [ 1.10, 2.20, 3.30, 4.40, 5.50 ] |
+ template: '"{{#list}}({{.}}){{/list}}"' |
+ expected: '"(1.1)(2.2)(3.3)(4.4)(5.5)"' |
+ |
+ # Dotted Names |
+ |
+ - name: Dotted Names - Truthy |
+ desc: Dotted names should be valid for Section tags. |
+ data: { a: { b: { c: true } } } |
+ template: '"{{#a.b.c}}Here{{/a.b.c}}" == "Here"' |
+ expected: '"Here" == "Here"' |
+ |
+ - name: Dotted Names - Falsey |
+ desc: Dotted names should be valid for Section tags. |
+ data: { a: { b: { c: false } } } |
+ template: '"{{#a.b.c}}Here{{/a.b.c}}" == ""' |
+ expected: '"" == ""' |
+ |
+ - name: Dotted Names - Broken Chains |
+ desc: Dotted names that cannot be resolved should be considered falsey. |
+ data: { a: { } } |
+ template: '"{{#a.b.c}}Here{{/a.b.c}}" == ""' |
+ expected: '"" == ""' |
+ |
+ # Whitespace Sensitivity |
+ |
+ - name: Surrounding Whitespace |
+ desc: Sections should not alter surrounding whitespace. |
+ data: { boolean: true } |
+ template: " | {{#boolean}}\t|\t{{/boolean}} | \n" |
+ expected: " | \t|\t | \n" |
+ |
+ - name: Internal Whitespace |
+ desc: Sections should not alter internal whitespace. |
+ data: { boolean: true } |
+ template: " | {{#boolean}} {{! Important Whitespace }}\n {{/boolean}} | \n" |
+ expected: " | \n | \n" |
+ |
+ - name: Indented Inline Sections |
+ desc: Single-line sections should not alter surrounding whitespace. |
+ data: { boolean: true } |
+ template: " {{#boolean}}YES{{/boolean}}\n {{#boolean}}GOOD{{/boolean}}\n" |
+ expected: " YES\n GOOD\n" |
+ |
+ - name: Standalone Lines |
+ desc: Standalone lines should be removed from the template. |
+ data: { boolean: true } |
+ template: | |
+ | This Is |
+ {{#boolean}} |
+ | |
+ {{/boolean}} |
+ | A Line |
+ expected: | |
+ | This Is |
+ | |
+ | A Line |
+ |
+ - name: Indented Standalone Lines |
+ desc: Indented standalone lines should be removed from the template. |
+ data: { boolean: true } |
+ template: | |
+ | This Is |
+ {{#boolean}} |
+ | |
+ {{/boolean}} |
+ | A Line |
+ expected: | |
+ | This Is |
+ | |
+ | A Line |
+ |
+ - name: Standalone Line Endings |
+ desc: '"\r\n" should be considered a newline for standalone tags.' |
+ data: { boolean: true } |
+ template: "|\r\n{{#boolean}}\r\n{{/boolean}}\r\n|" |
+ expected: "|\r\n|" |
+ |
+ - name: Standalone Without Previous Line |
+ desc: Standalone tags should not require a newline to precede them. |
+ data: { boolean: true } |
+ template: " {{#boolean}}\n#{{/boolean}}\n/" |
+ expected: "#\n/" |
+ |
+ - name: Standalone Without Newline |
+ desc: Standalone tags should not require a newline to follow them. |
+ data: { boolean: true } |
+ template: "#{{#boolean}}\n/\n {{/boolean}}" |
+ expected: "#\n/\n" |
+ |
+ # Whitespace Insensitivity |
+ |
+ - name: Padding |
+ desc: Superfluous in-tag whitespace should be ignored. |
+ data: { boolean: true } |
+ template: '|{{# boolean }}={{/ boolean }}|' |
+ expected: '|=|' |