This is a conformance suite taken (with small adjustments) from Mike Samuel's jQuery Templates implementation proposal, for testing conformance of JsRender.
Each row in the tables below is a test case.
This is work in progress. Note that not all the cases correspond exactly to an agreed jQuery Templates grammar. The grammar here is close, but not yet definitive. The following documentation, though less detailed, is definitive for the current jQuery Templates design.
The "test" column includes the literal text of a template wrapped in
an <xmp>
element.
The "data" column includes a data value as JavaScript text also
wrapped in an <xmp>
.
The "expected" column shows the expected output of the template when compiled and applied to the data. If the output starts with "Error:" then the compilation or application should fail with an exception, and in debug mode should produce the following error message.
The "actual" column is auto-generated and contains the actual result and is colored to indicate success or failure.
The right-most column, if any, includes explatory text about the test-case.
Any "test" cells whose content consists of named templates specified via
<script type="text/x-jquery-tmpl" id="template-name">
elements will have all templates extracted and compiled as a bundle
and the template with id="main"
will be the one applied.
To test the reference implementation, add
?reference
to the URL.
To test the reference implementation, add
?compressed
to the URL.
To run just some tests, add ?testFilter=<RegExp>
where <RegExp>
matches the right-most column, the
test description.
To turn off logging to the console, add ?nolog
to the URL.
The tests below test the built-in operators that ship by default.
Test | Data | Expected | Actual | |||||||
---|---|---|---|---|---|---|---|---|---|---|
Empty Template | ||||||||||
Hello, World! | Plain text | |||||||||
Hello, <World>! | HTML entities preserved | |||||||||
𐀀 | 𐀀 | Supplemental codepoints preserved | ||||||||
- | - | Orphaned surrogates preserved | ||||||||
foo bar | Newlines preserved. | |||||||||
a b${'\u2029'}c | a b c | Unusual newlines | ||||||||
Hello, World! | HTML tags preserved | |||||||||
It costs $5, 5$. {if} {{/- {{. | Dollars and curlies in text | |||||||||
Cow says mfoo, dog says bark | Substitution | |||||||||
Cow says mfoo, dog says bark | Substitution unabbreviated syntax | |||||||||
Hello, ! | Substitution w/out data | |||||||||
i=42, f=0.5, nf=-0.5, nan=NaN, inf=Infinity, nzero=0 | Substitution numbers | |||||||||
s=Hello, World!, n=42, nul=, supp=𐀀 | Substitution strings | |||||||||
orphans=- | Substitution non-unicode strings | |||||||||
t=true, f=false | Substitution booleans | |||||||||
s=foo, o=[Obj], thunk=Hello, World!, a=1,2,3 | Substitution objects | |||||||||
Hello, string! | toString vs valueOf | |||||||||
i++=0, i++=1, readOnce=42, counter=1, counter=2 | Substitution evaluation happens once and in order | |||||||||
${breaker} |
-->]]></script></style></textarea>" ' ) > |
Substitution autoescaped | ||||||||
Hello, Cincinatti! | If branch taken | |||||||||
Goodbye, Cleveland! | Else branch taken | |||||||||
Hello, Cincinatti! | If branch taken no else | |||||||||
, Cleveland! | No else branch | |||||||||
Goodbye, Cincinatti! | Condition in else taken | |||||||||
, Cincinatti! | Condition in else not taken | |||||||||
Hello, Cincinatti! | If branch taken based on truthy value | |||||||||
Goodbye, Cleveland! | Else branch taken based on falsey value | |||||||||
|
|
Loop over array | ||||||||
|
Loop over empty | |||||||||
|
|
Loop with custom key variable name | ||||||||
|
|
Loop with custom variable names | ||||||||
|
|
Loop over associative array. | ||||||||
this x=x, that x=(x) | Template Calls | |||||||||
Error:Invalid {{tmpl}} content: ({ x, y }) "#that" | Invalid Template Param | |||||||||
Error:Invalid {{tmpl}} content: ({ x: y }) "#that | Invalid Template Selector | |||||||||
this x=x, that x=(y) | Call with different data | |||||||||
this x=1, that x=(3) | Template Order of Evaluation | |||||||||
11 | String concatenation of adjacent subs | |||||||||
2 | Arithmetic in substitution | |||||||||
a[0].b[cStr]=42 | Member expressions | |||||||||
undef= | Undefined member | |||||||||
-... | Recursive template | |||||||||
none | Unreached variable need not be defined | |||||||||
Error:Unclosed block directives if in {{if cond}}foo{{else}} | Missing {{/if}} error message | |||||||||
Error:{{else}} without condition must be last:{{if cond}}foo{{else}}bar{{else}}boo{{/if}} | Misplaced {{else}} | |||||||||
Error:{{if}} missing condition:{{if }}foo{{/if}} | Missing {{if}} condition | |||||||||
Error:I do not know how to compile {{unknown}} | Unknown directive name | |||||||||
Error:Invalid template substitution: i + (j | Catch obviously broken expressions early. | |||||||||
Error:Invalid template substitution: String()) } { (String() | Unbracketing and rebracketing illegal. | |||||||||
42 | "arguments" as a data key | |||||||||
[object Object] | "arguments" not present as a data key | |||||||||
"arguments[0]" not present | ||||||||||
42, 42 | "arguments" present as a data key | |||||||||
42 | Template options available | |||||||||
option,data,option | Data masking template options | |||||||||
option,option2,option | Passing options | |||||||||
true | Maintain data identity |