preserve/events/helpers tests (and fixes)

This commit is contained in:
David Greenspan
2012-08-13 10:45:04 -07:00
parent ded6c4901b
commit 2ddf2b1f83
5 changed files with 154 additions and 4 deletions

View File

@@ -136,7 +136,7 @@ Handlebars.evaluate = function (ast, data, options) {
var dataThis = stack.data;
var data;
if (id[0] === 0 && (id[1] in helpers) && ! scopedToContext) {
if (id[0] === 0 && helpers.hasOwnProperty(id[1]) && ! scopedToContext) {
// first path segment is a helper
data = helpers[id[1]];
} else {

View File

@@ -70,7 +70,8 @@
// XXX forms hooks into this to add "bind"?
Meteor._template_decl_methods = {
_tmpl_data: {}, // methods store data here (event map, etc.)
// methods store data here (event map, etc.). initialized per template.
_tmpl_data: null,
// these functions must be generic (i.e. use `this`)
events: function (eventMap) {
var events =
@@ -90,7 +91,7 @@
},
helpers: function (helperMap) {
var helpers =
(this._tmpl_data.events = (this._tmpl_data.events || {}));
(this._tmpl_data.helpers = (this._tmpl_data.helpers || {}));
for(var h in helperMap)
helpers[h] = helperMap[h];
}
@@ -179,6 +180,7 @@
Template[name] = partial;
_.extend(partial, Meteor._template_decl_methods);
partial._tmpl_data = {};
Meteor._partials[name] = partial;
}

View File

@@ -111,7 +111,8 @@ var html_scanner = {
_handleTag: function (results, tag, attribs, contents, parseError) {
// trim the tag contents
// trim the tag contents.
// this is a courtesy and is also relied on by some unit tests.
contents = contents.match(/^[ \t\r\n]*([\s\S]*?)[ \t\r\n]*$/)[1];
// do we have 1 or more attribs?

View File

@@ -234,3 +234,35 @@
<template name="test_template_arg_a">
<b>Foo</b> <i>Bar</i> <u>Baz</u>
</template>
<template name="test_template_preserve_a">
<span class="a">x</span>
<span class="b">x</span>
<span class="c">x</span>
<span class="d">x</span>
<span class="y">x</span>
<span class="e">x</span>
<span class="z">x</span>
<span class="f">x</span>
{{var}}
</template>
<template name="test_template_helpers_a">
{{foo}}{{bar}}{{baz}}
</template>
<template name="test_template_helpers_b">
{{name}}{{arity}}{{toString}}{{length}}{{var}}
</template>
<template name="test_template_helpers_c">
{{name}}{{arity}}{{toString}}{{length}}{{var}}
</template>
<template name="test_template_events_a">
<b>foo</b><u>bar</u><i>baz</i>
</template>
<template name="test_template_events_b">
<b>foo</b><u>bar</u><i>baz</i>
</template>

View File

@@ -619,3 +619,118 @@ Tinytest.add("templating - template arg", function (test) {
div.kill();
Meteor.flush();
});
Tinytest.add("templating - preserve", function (test) {
var R = ReactiveVar('foo');
var tmpl = Template.test_template_preserve_a;
tmpl.preserve(['.b']);
tmpl.preserve(['.c']);
tmpl.preserve({'.d': true});
tmpl.preserve({'span': function (n) {
return _.contains(['e','f'], n.className) && n.className;
}});
tmpl.preserve(['span.a']);
tmpl['var'] = function () { return R.get(); };
var div = OnscreenDiv(Meteor.render(tmpl));
Meteor.flush();
test.equal(div.node().lastChild.nodeValue.match(/\S+/)[0], 'foo');
var spans1 = {};
_.each(DomUtils.findAll(div.node(), 'span'), function (sp) {
spans1[sp.className] = sp;
});
R.set('bar');
Meteor.flush();
test.equal(div.node().lastChild.nodeValue.match(/\S+/)[0], 'bar');
var spans2 = {};
_.each(DomUtils.findAll(div.node(), 'span'), function (sp) {
spans2[sp.className] = sp;
});
test.isTrue(spans1.a === spans2.a);
test.isTrue(spans1.b === spans2.b);
test.isTrue(spans1.c === spans2.c);
test.isTrue(spans1.d === spans2.d);
test.isTrue(spans1.e === spans2.e);
test.isTrue(spans1.f === spans2.f);
test.isFalse(spans1.y === spans2.y);
test.isFalse(spans1.z === spans2.z);
div.kill();
Meteor.flush();
});
Tinytest.add("templating - helpers", function (test) {
var tmpl = Template.test_template_helpers_a;
tmpl.foo = 'z';
tmpl.helpers({bar: 'b'});
// helpers(...) takes precendence of assigned helper
tmpl.helpers({foo: 'a', baz: function() { return 'c'; }});
var div = OnscreenDiv(Meteor.render(tmpl));
test.equal(div.text().match(/\S+/)[0], 'abc');
div.kill();
Meteor.flush();
tmpl = Template.test_template_helpers_b;
tmpl.helpers({
'name': 'A',
'arity': 'B',
'toString': 'C',
'length': 4,
'var': 'D'
});
div = OnscreenDiv(Meteor.render(tmpl));
test.equal(div.text().match(/\S+/)[0], 'ABC4D');
div.kill();
Meteor.flush();
// test that helpers don't "leak"
tmpl = Template.test_template_helpers_c;
div = OnscreenDiv(Meteor.render(tmpl));
test.equal(div.text(), '');
div.kill();
Meteor.flush();
});
Tinytest.add("templating - events", function (test) {
var tmpl = Template.test_template_events_a;
var buf = [];
// old style
tmpl.events = {
'click b': function () { buf.push('b'); }
};
var div = OnscreenDiv(Meteor.render(tmpl));
clickElement(DomUtils.find(div.node(), 'b'));
test.equal(buf, ['b']);
div.kill();
Meteor.flush();
///
tmpl = Template.test_template_events_b;
buf = [];
// new style
tmpl.events({
'click u': function () { buf.push('u'); }
});
tmpl.events({
'click i': function () { buf.push('i'); }
});
var div = OnscreenDiv(Meteor.render(tmpl));
clickElement(DomUtils.find(div.node(), 'u'));
clickElement(DomUtils.find(div.node(), 'i'));
test.equal(buf, ['u', 'i']);
div.kill();
Meteor.flush();
});