From a17b2e4bf2805a78bbedfc2dc4bcee3dabd25d93 Mon Sep 17 00:00:00 2001 From: David Greenspan Date: Mon, 13 Aug 2012 12:41:20 -0700 Subject: [PATCH] test that all list mods trigger render() (fails) --- packages/templating/deftemplate.js | 4 +- packages/templating/templating_tests.html | 12 ++++ packages/templating/templating_tests.js | 87 +++++++++++++++++++++++ 3 files changed, 102 insertions(+), 1 deletion(-) diff --git a/packages/templating/deftemplate.js b/packages/templating/deftemplate.js index 746791b439..2c3ec1b84b 100644 --- a/packages/templating/deftemplate.js +++ b/packages/templating/deftemplate.js @@ -9,7 +9,9 @@ var orig = Handlebars._default_helpers.each; Handlebars._default_helpers.each = function (arg, options) { - if (!(arg instanceof LocalCollection.Cursor)) + // if arg isn't an observable (like LocalCollection.Cursor), + // don't use this reactive implementation of #each. + if (!(arg && 'observe' in arg)) return orig.call(this, arg, options); return Spark.list( diff --git a/packages/templating/templating_tests.html b/packages/templating/templating_tests.html index f6e9d05d8d..587eb7b1e1 100644 --- a/packages/templating/templating_tests.html +++ b/packages/templating/templating_tests.html @@ -266,3 +266,15 @@ + + + + diff --git a/packages/templating/templating_tests.js b/packages/templating/templating_tests.js index 11c5cd9718..eae1493e17 100644 --- a/packages/templating/templating_tests.js +++ b/packages/templating/templating_tests.js @@ -734,3 +734,90 @@ Tinytest.add("templating - events", function (test) { Meteor.flush(); }); + +Tinytest.add("templating - #each render callback", function (test) { + // test that any list modification triggers a render callback on the + // enclosing template + + var entries = new LocalCollection(); + entries.insert({x:'a'}); + entries.insert({x:'b'}); + entries.insert({x:'c'}); + + var buf = []; + + var tmpl = Template.test_template_eachrender_a; + tmpl.helpers({entries: function() { + return entries.find({}, {sort: ['x']}); }}); + tmpl.render = function () { + buf.push(canonicalizeHtml( + DomUtils.rangeToHtml(this.firstNode, this.lastNode)).replace(/\s/g, '')); + }; + var div = OnscreenDiv(Meteor.render(tmpl)); + Meteor.flush(); + test.equal(buf, ['
a
b
c
']); + buf.length = 0; + + // added + entries.insert({x:'d'}); + test.equal(buf, []); + Meteor.flush(); + test.equal(buf, ['
a
b
c
d
']); + buf.length = 0; + + // removed + entries.remove({x:'a'}); + test.equal(buf, []); + Meteor.flush(); + test.expect_fail(); + test.equal(buf, ['
b
c
d
']); + buf.length = 0; + + // moved/changed + entries.update({x:'b'}, {$set: {x: 'z'}}); + test.equal(buf, []); + Meteor.flush(); + test.equal(buf, ['
c
d
z
']); + buf.length = 0; + + // test pure "moved" + + tmpl = Template.test_template_eachrender_b; + var cbks = []; + var xs = ['a','b','c']; + tmpl.helpers({entries: function() { + return { observe: function (callbacks) { + cbks.push(callbacks); + _.each(xs, function(x, i) { + callbacks.added({x:x}, i); + }); + return { + stop: function () { + cbks = _.without(cbks, callbacks); + } + }; + }}; + }}); + tmpl.render = function () { + buf.push(canonicalizeHtml( + DomUtils.rangeToHtml(this.firstNode, this.lastNode)).replace(/\s/g, '')); + }; + buf = []; + var div = OnscreenDiv(Meteor.render(tmpl)); + test.equal(buf, []); + Meteor.flush(); + test.equal(buf, ['
a
b
c
']); + buf.length = 0; + + _.each(cbks, function (callbacks) { + callbacks.moved({x:'a'}, 0, 2); + }); + test.equal(buf, []); + Meteor.flush(); + test.equal(div.html().replace(/\s/g, ''), + '
b
c
a
'); + test.expect_fail(); + test.equal(buf, ['
b
c
a
']); + buf.length = 0; + +});