AutorÃa | Ultima modificación | Ver Log |
/*global test, equal, module, ok*/
(function(global, $, undefined) {
"use strict";
var isIE8 = window.attachEvent && !window.addEventListener;
function sort(array) {
var ret = "";
if (this.tagCtx.props.reverse) {
// Render in reverse order
for (var i = array.length; i; i--) {
ret += this.tagCtx.render(array[ i - 1 ]);
}
} else {
// Render in original order
ret += this.tmpl.render(array);
}
return ret;
}
var person = {name: "Jo"},
people = [{name: "Jo"},{name: "Bill"}],
towns = [{name: "Seattle"},{name: "Paris"},{name: "Delhi"}];
var tmplString = "A_{{:name}}_B";
QUnit.module("api");
QUnit.test("templates", function(assert) {
var tmplElem = document.getElementById("./test/templates/file/path.html");
// =============================== Arrange ===============================
$.removeData(tmplElem, "jsvTmpl"); // In case data has been set in a previous test
// ................................ Act ..................................
var tmpl0 = $.templates({markup: "./test/templates/file/path.html"}); // Compile template but do not cache
// ............................... Assert .................................
assert.equal(!$.data(tmplElem).jsvTmpl && tmpl0.render({name: "Jo0"}), isIE8 ? "\nServerRenderedTemplate_Jo0_B" : "ServerRenderedTemplate_Jo0_B", "Compile server-generated template, without caching");
// ................................ Act ..................................
var tmpl1 = $.templates("./test/templates/file/path.html"); // Compile and cache, using $.data(elem, "jsvTmpl", tmpl);
// ............................... Assert .................................
assert.equal(tmpl1 !== tmpl0 && $.data(tmplElem).jsvTmpl === tmpl1 && tmpl1.render({name: "Jo1"}), isIE8 ? "\nServerRenderedTemplate_Jo1_B" : "ServerRenderedTemplate_Jo1_B", "Compile server-generated template, and cache on file path");
// ................................ Act ..................................
var tmpl2 = $.templates("./test/templates/file/path.html"); // Use cached template, accessed by path as key
// ............................... Assert .................................
assert.equal(tmpl2 === tmpl1 && tmpl1.render({name: "Jo2"}), isIE8 ? "\nServerRenderedTemplate_Jo2_B" : "ServerRenderedTemplate_Jo2_B", "Re-use cached server-generated template");
// ................................ Act ..................................
var tmpl3 = $.templates({markup: "./test/templates/file/path.html"}); // Re-compile template but do not cache. Leaved cached template.
// ............................... Assert .................................
assert.equal(tmpl3 !== tmpl0 && tmpl3 !== tmpl1 && $.data(tmplElem).jsvTmpl === tmpl1 && tmpl3.render({name: "Jo3"}), isIE8 ? "\nServerRenderedTemplate_Jo3_B" : "ServerRenderedTemplate_Jo3_B", "Recompile server-generated template, without caching");
// ................................ Reset ................................
delete $.data(tmplElem).jsvTmpl;
document.getElementById("./test/templates/file/path.html").removeAttribute("data-jsv-tmpl");
tmplElem = $("#myTmpl")[0];
delete $.data(tmplElem).jsvTmpl;
tmplElem.removeAttribute("data-jsv-tmpl");
// ................................ Act ..................................
tmpl0 = $.templates({markup: "#myTmpl"}); // Compile template declared in script block, but do not cache
// ............................... Assert .................................
assert.equal(!$.data(tmplElem).jsvTmpl && tmpl0.render({name: "Jo0"}), isIE8 ? "\nA_Jo0_B" : "A_Jo0_B", "Compile template declared in script block, without caching");
// ................................ Act ..................................
tmpl1 = $.templates("#myTmpl"); // Compile and cache, using $.data(elem, "jsvTmpl", tmpl);
// ............................... Assert .................................
assert.equal(tmpl1 !== tmpl0 && $.data(tmplElem).jsvTmpl === tmpl1 && tmpl1.render({name: "Jo1"}), isIE8 ? "\nA_Jo1_B" : "A_Jo1_B", "Compile template declared in script block, and cache on file path");
// ................................ Act ..................................
tmpl2 = $.templates("#myTmpl"); // Use cached template, accessed by $.data(elem, "jsvTmpl")
// ............................... Assert .................................
assert.equal(tmpl2 === tmpl1 && tmpl1.render({name: "Jo2"}), isIE8 ? "\nA_Jo2_B" : "A_Jo2_B", "Re-use cached template declared in script block");
// ................................ Act ..................................
tmpl3 = $.templates({markup: "#myTmpl"}); // Re-compile template but do not cache. Leave cached template.
// ............................... Assert .................................
assert.equal(tmpl3 !== tmpl0 && tmpl3 !== tmpl1 && $.data(tmplElem).jsvTmpl === tmpl1 && tmpl3.render({name: "Jo3"}), isIE8 ? "\nA_Jo3_B" : "A_Jo3_B", "Recompile template declared in script block, without caching");
// ................................ Reset ................................
delete $.data(tmplElem).jsvTmpl;
tmplElem.removeAttribute("data-jsv-tmpl");
// =============================== Arrange ===============================
// ............................... Assert .................................
assert.equal($.templates("#my_tmpl2").render(), isIE8 ? "\n' \" \\ \\' \\\"" : "' \" \\ \\' \\\"", "correct treatment of ' \" and ' in template declared in script block");
assert.equal($.templates("' \" \\ \\' \\\"").render(), "' \" \\ \\' \\\"", "correct treatment of ' \" and ' in template compiled from string");
$.templates("my_tmpl", tmplString);
assert.equal($.render.my_tmpl(person), "A_Jo_B", 'Compile a template and then render it: $.templates("my_tmpl", tmplString); $.render.my_tmpl(data);');
$.templates({myTmpl2: tmplString});
assert.equal($.render.myTmpl2(person), "A_Jo_B", 'Compile and register templates: $.templates({"my_tmpl", tmplString, ...}); $.render.my_tmpl(data);');
assert.equal($.templates.myTmpl2.render(person), "A_Jo_B", 'Get named template: $.templates.my_tmpl.render(data);');
assert.equal($.templates(tmplString).render(person), "A_Jo_B", 'Compile without registering as named template: $.templates(tmplString).render(person);');
tmpl2 = $.templates("#my_tmpl");
tmpl3 = $.templates("#my_tmpl");
assert.equal(tmpl2 === tmpl3 && $.trim(tmpl2.render(person)), "A_Jo_B", 'var tmpl = $.templates("#my_tmpl"); returns compiled template for script element');
$.templates({
my_tmpl3: {
markup: "#my_tmpl"
}
});
assert.equal($.render.my_tmpl3 === $.templates.my_tmpl3 && $.templates.my_tmpl3 !== tmpl2 && $.trim($.render.my_tmpl3(person)), "A_Jo_B", 'Named template for template object with selector: {markup: "#my_tmpl"}');
tmpl3 = $.templates("", {
markup: "#my_tmpl"
});
assert.equal($.trim(tmpl3.render(person)), "A_Jo_B", 'Compile from template object with selector, without registering: {markup: "#my_tmpl"}');
var tmpl4 = $.templates({
markup: "#my_tmpl"
});
assert.equal($.trim(tmpl4.render(person)), "A_Jo_B", 'Compile from template object with selector, without registering: {markup: "#my_tmpl"}');
assert.equal($.templates("#my_tmpl"), $.templates("#my_tmpl"), '$.templates("#my_tmpl") caches compiled template, and does not recompile each time;');
assert.ok($.templates({markup: "#my_tmpl"}) !== $.templates({markup: "#my_tmpl"}), '$.templates({markup: "#my_tmpl" ...}) recompiles template, so as to merge additional options;');
assert.equal($.templates("", "#my_tmpl"), $.templates("#my_tmpl"), '$.templates("#my_tmpl") and $.templates("", "#my_tmpl") are equivalent');
var renamed = $.templates("renamed", "#my_tmpl");
assert.ok(renamed === tmpl2 && renamed.tmplName === "renamed", '$.templates("renamed", "#my_tmpl") will rename the cached template');
$.templates({renamed2: "#my_tmpl"});
assert.ok($.templates.renamed2 === tmpl2 && $.templates.renamed2.tmplName === "renamed2", '$.templates({renamed2: "#my_tmpl"}) will rename the cached template');
$.templates("cloned", {markup: "#my_tmpl"});
assert.ok($.templates.cloned !== tmpl2 && $.templates.cloned.tmplName === "cloned", '$.templates("cloned", {markup: "#my_tmpl"}}) will clone the cached template');
$.templates({cloned2: {markup: "#my_tmpl"}});
assert.ok($.templates.cloned2 !== tmpl2 && $.templates.cloned2.tmplName === "cloned2", '$.templates({cloned: {markup: "#my_tmpl"}}) will clone the cached template');
$.templates("my_tmpl", null);
assert.equal($.templates.my_tmpl, undefined, 'Remove a named template: $.templates("my_tmpl", null);');
$.templates({
scriptTmpl: {
markup: "#my_tmpl",
debug:true
},
tmplFromString: {
markup: "X_{{:name}}_Y",
debug:true
}
});
assert.equal($.templates.tmplFromString.fn.toString().indexOf("debugger;") > 0
&& $.templates.scriptTmpl.fn.toString().indexOf("debugger;") > 0
&& $.templates.scriptTmpl({name: "Jo"}) + $.templates.tmplFromString({name: "Jo"}), isIE8
? "\nA_Jo_BX_Jo_Y"
: "A_Jo_BX_Jo_Y",
'Debug a template: set debug:true on object');
// reset
$("#my_tmpl")[0].removeAttribute("data-jsv-tmpl");
delete $.templates.scriptTmpl;
});
QUnit.test("render", function(assert) {
assert.equal($.trim($("#my_tmpl").render(person)), "A_Jo_B", '$(tmplSelector).render(data);'); // Trimming because IE adds whitespace
var tmpl3 = $.templates("my_tmpl4", tmplString);
assert.equal($.render.my_tmpl4(person), "A_Jo_B", '$.render.my_tmpl(object);');
assert.equal($.render.my_tmpl4(people), "A_Jo_BA_Bill_B", '$.render.my_tmpl(array);');
var tmplObject = $.templates.my_tmpl4;
assert.equal(tmplObject.render(people), "A_Jo_BA_Bill_B", 'var tmplObject = $.templates.my_tmpl; tmplObject.render(data);');
$.templates("my_tmpl5", "A_{{for}}inner{{:name}}content{{/for}}_B");
assert.equal($.templates.my_tmpl5.tmpls[0].render(person), "innerJocontent", 'Nested template objects: $.templates.my_tmpl.tmpls');
$("#result").html("<script id='tmpl' type='text/x-jsrender'>Content{{for #data}}{{:#index}}{{/for}}{{:~foo}}</script>");
assert.equal($("#tmpl").render([null,undefined,1], {foo:"foovalue"}, true), (isIE8 ? "\n" : "") + "Content012foovalue", 'render(array, helpers, true) renders an array without iteration, while passing in helpers');
$("#result").html("<script id='tmpl' type='text/x-jsrender'>Content{{for #data}}{{:#index}}{{/for}}{{:~foo}}</script>");
assert.equal($("#tmpl").render([null, undefined, 1], true), (isIE8 ? "\n" : "") + "Content012", 'render(array, true) renders an array without iteration');
$("#result").empty();
});
QUnit.test("converters", function(assert) {
function loc(data) {
switch (data) {case "desktop": return "bureau"; }
}
$.views.converters({loc: loc});
assert.equal($.templates("{{loc:#data}}:{{loc:'desktop'}}").render("desktop"), "bureau:bureau", "$.views.converters({loc: locFunction})");
$.views.converters("loc2", loc);
assert.equal($.views.converters.loc2 === loc, true, 'locFunction === $.views.converters.loc');
$.views.converters({loc2: null});
assert.equal($.views.converters.loc2, undefined, 'Remove a registered converter: $.views.converters({loc: null})');
});
QUnit.test("tags", function(assert) {
$.views.tags({sort1: sort});
assert.equal($.templates("{{sort1 people reverse=true}}{{:name}}{{/sort1}}").render({people: people}), "BillJo", "$.views.tags({sort: sortFunction})");
$.views.tags("sort2", sort);
assert.equal($.views.tags.sort1.render === sort, true, 'sortFunction === $.views.tags.sort');
$.views.tags("sort2", null);
assert.equal($.views.tags.sort2, undefined, 'Remove a registered tag: $.views.tag({sor: null})');
});
QUnit.test("helpers", function(assert) {
function concat() {
return "".concat.apply("", arguments);
}
$.views.helpers({
not: function(value) {
return !value;
},
concat: concat
});
assert.equal($.templates("{{:~concat(a, 'b', ~not(false))}}").render({a: "aVal"}), "aValbtrue", "$.views.helpers({concat: concatFunction})");
$.views.helpers({concat2: concat});
assert.equal($.views.helpers.concat === concat, true, 'concatFunction === $.views.helpers.concat');
$.views.helpers("concat2", null);
assert.equal($.views.helpers.concat2, undefined, 'Remove a registered helper: $.views.helpers({concat: null})');
});
QUnit.test("template encapsulation", function(assert) {
$.templates({
myTmpl6: {
markup: "{{sort reverse=true people}}{{:name}}{{/sort}}",
tags: {
sort: sort
}
}
});
assert.equal($.render.myTmpl6({people: people}), "BillJo", '$.templates("my_tmpl", tmplObjWithNestedItems);');
});
QUnit.test("$.views.viewModels", function(assert) {
// =============================== Arrange ===============================
var Constr = $.views.viewModels({getters: ["a", "b"]});
// ................................ Act ..................................
var vm = Constr("a1 ", "b1 ");
var result = vm.a() + vm.b();
vm.a("a2 ");
vm.b("b2 ");
result += vm.a() + vm.b();
// ............................... Assert .................................
assert.equal(result, "a1 b1 a2 b2 ", "viewModels, two getters, no methods");
// =============================== Arrange ===============================
Constr = $.views.viewModels({getters: ["a", "b", "c"], extend: {add: function(val) {
this.c(val + this.a() + this.b() + this.c());
}}});
// ................................ Act ..................................
vm = Constr("a1 ", "b1 ", "c1 ");
vm.add("before ");
result = vm.c();
// ............................... Assert .................................
assert.equal(result, "before a1 b1 c1 ", "viewModels, two getters, one method");
// =============================== Arrange ===============================
Constr = $.views.viewModels({extend: {add: function(val) {
this.foo = val;
}}});
// ................................ Act ..................................
vm = Constr();
vm.add("before");
result = vm.foo;
// ............................... Assert .................................
assert.equal(result, "before", "viewModels, no getters, one method");
// =============================== Arrange ===============================
Constr = $.views.viewModels({getters: []});
// ................................ Act ..................................
vm = Constr();
result = JSON.stringify(vm);
// ............................... Assert .................................
assert.equal(result, "{}", "viewModels, no getters, no methods");
// =============================== Arrange ===============================
$.views.viewModels({
T1: {
getters: ["a", "b"]
}
});
// ................................ Act ..................................
vm = $.views.viewModels.T1.map({a: "a1 ", b: "b1 "});
result = vm.a() + vm.b();
vm.a("a2 ");
vm.b("b2 ");
result += vm.a() + vm.b();
// ............................... Assert .................................
assert.equal(result, "a1 b1 a2 b2 ", "viewModels, two getters, no methods");
// ................................ Act ..................................
vm.merge({a: "a3 ", b: "b3 "});
result = vm.a() + vm.b();
// ............................... Assert .................................
assert.equal(result, "a3 b3 ", "viewModels merge, two getters, no methods");
// ................................ Act ..................................
result = vm.unmap();
result = JSON.stringify(result);
// ............................... Assert .................................
assert.equal(result, '{"a":"a3 ","b":"b3 "}', "viewModels unmap, two getters, no methods");
// =============================== Arrange ===============================
var viewModels = $.views.viewModels({
T1: {
getters: ["a", {getter: "b"}, "c", "d", {getter: "e", type: undefined}, {getter: "f", type: null}, {getter: "g", type: "foo"}, {getter: "h", type: ""}]
}
}, {});
// ................................ Act ..................................
vm = viewModels.T1.map({a: "a1 ", b: "b1 ", c: "c1 ", d: "d1 ", e: "e1 ", f: "f1 ", g: "g1 ", h: "h1 "});
result = vm.a() + vm.b() + vm.c() + vm.d() + vm.e() + vm.f() + vm.g() + vm.h();
vm.a("a2 ");
vm.b("b2 ");
result += vm.a() + vm.b();
// ............................... Assert .................................
assert.equal(result, "a1 b1 c1 d1 e1 f1 g1 h1 a2 b2 ",
"viewModels, multiple unmapped getters, no methods");
// ................................ Act ..................................
vm.merge({a: "a3 ", b: "b3 ", c: "c3 ", d: "d3 ", e: "e3 ", f: "f3 ", g: "g3 ", h: "h3 "});
result = vm.a() + vm.b() + vm.c() + vm.d() + vm.e() + vm.f() + vm.g() + vm.h();
// ............................... Assert .................................
assert.equal(result, "a3 b3 c3 d3 e3 f3 g3 h3 ",
"viewModels merge, multiple unmapped getters, no methods");
// ................................ Act ..................................
result = vm.unmap();
result = JSON.stringify(result);
// ............................... Assert .................................
assert.equal(result, '{"a":"a3 ","b":"b3 ","c":"c3 ","d":"d3 ","e":"e3 ","f":"f3 ","g":"g3 ","h":"h3 "}',
"viewModels unmap, multiple unmapped getters, no methods");
// =============================== Arrange ===============================
$.views.viewModels({
T1: {
getters: ["a", "b", "c"],
extend : {
add: function(val) {
this.c(val + this.a() + this.b() + this.c());
}
}
}
});
// ................................ Act ..................................
vm = $.views.viewModels.T1.map({a: "a1 ", b: "b1 ", c: "c1 "});
vm.add("before ");
result = vm.c();
// ............................... Assert .................................
assert.equal(result, "before a1 b1 c1 ", "viewModels, getters and one method");
// ................................ Act ..................................
vm.merge({a: "a3 ", b: "b3 ", c: "c3 "});
vm.add("updated ");
result = vm.c();
// ............................... Assert .................................
assert.equal(result, "updated a3 b3 c3 ", "viewModels merge, getters and one method");
// ................................ Act ..................................
result = vm.unmap();
result = JSON.stringify(result);
// ............................... Assert .................................
assert.equal(result, '{"a":"a3 ","b":"b3 ","c":"updated a3 b3 c3 "}', "viewModels unmap, getters and one method");
// =============================== Arrange ===============================
$.views.viewModels({
T1: {
getters: ["a", "b"]
},
T2: {
getters: [{getter: "t1", type: "T1"}, {getter: "t1Arr", type: "T1"}, {getter: "t1OrNull", type: "T1", defaultVal: null}]
}
});
viewModels = $.views.viewModels;
// ................................ Act ..................................
var t1 = viewModels.T1.map({a: "a1 ", b: "b1 "}); // Create a T1
var t2 = viewModels.T2.map({t1: {a: "a3 ", b: "b3 "}, t1Arr: [t1.unmap(), {a: "a2 ", b: "b2 "}]}); // Create a T2 (using unmap to scrape values the T1: vm)
result = JSON.stringify(t2.unmap());
// ............................... Assert .................................
assert.equal(result, '{"t1":{"a":"a3 ","b":"b3 "},"t1Arr":[{"a":"a1 ","b":"b1 "},{"a":"a2 ","b":"b2 "}],"t1OrNull":null}',
"viewModels, hierarchy");
// ................................ Act ..................................
t2.t1Arr()[0].merge({a: "a1x ", b: "b1x "}); // merge not the root, but a VM instance within hierarchy: vm2.t1Arr()[0] - leaving rest unchanged
result = JSON.stringify(t2.unmap());
// ............................... Assert .................................
assert.equal(result, '{"t1":{"a":"a3 ","b":"b3 "},"t1Arr":[{"a":"a1x ","b":"b1x "},{"a":"a2 ","b":"b2 "}],"t1OrNull":null}',
"viewModels, merge deep node");
// ................................ Act ..................................
var t1Arr = viewModels.T1.map([{a: "a1 ", b: "b1 "}, {a: "a2 ", b: "b2 "}]); // Create a T1 array
var t2FromArr = viewModels.T2.map({t1: {a: "a3 ", b: "b3 "}, t1Arr: t1Arr.unmap()}); // Create a T2 (using unmap to scrape values the T1: vm)
result = JSON.stringify(t2FromArr.unmap());
// ............................... Assert .................................
assert.equal(result, '{"t1":{"a":"a3 ","b":"b3 "},"t1Arr":[{"a":"a1 ","b":"b1 "},{"a":"a2 ","b":"b2 "}],"t1OrNull":null}',
"viewModels, hierarchy");
// ................................ Act ..................................
t1Arr = viewModels.T1.map([{a: "a1 ", b: "b1 "}, {a: "a2 ", b: "b2 "}]); // Create a T1 array
t1Arr.push(viewModels.T1("a3 ", "b3 "));
t2FromArr = viewModels.T2.map({t1: {a: "a4 ", b: "b4 "}, t1Arr: t1Arr.unmap()}); // Create a T2 (using unmap to scrape values the T1: vm)
result = JSON.stringify(t2FromArr.unmap());
// ............................... Assert .................................
assert.equal(result, '{"t1":{"a":"a4 ","b":"b4 "},"t1Arr":[{"a":"a1 ","b":"b1 "},{"a":"a2 ","b":"b2 "},{"a":"a3 ","b":"b3 "}],"t1OrNull":null}',
"viewModels, hierarchy");
// ................................ Act ..................................
var t2new= viewModels.T2(viewModels.T1("a3 ", "b3 "), [viewModels.T1("a1 ", "b1 "), viewModels.T1("a2 ", "b2 ")], viewModels.T1("a4 ", "b4 "));
result = JSON.stringify(t2new.unmap());
// ............................... Assert .................................
assert.equal(result, '{"t1":{"a":"a3 ","b":"b3 "},"t1Arr":[{"a":"a1 ","b":"b1 "},{"a":"a2 ","b":"b2 "}],"t1OrNull":{"a":"a4 ","b":"b4 "}}',
"viewModels, hierarchy");
});
})(this, this.jQuery);