Skip to content

Commit

Permalink
Formalize populate to also trigger init_element
Browse files Browse the repository at this point in the history
- Given that workflows for triggering client-side rendering will happen
  after the page has loaded, i.e. after do_onload is typically called.
- In order to also properly hook that in place, call init_element after
  the populate is completed.
- The testing, especially for the missing module, had to be a bit obtuse
  for the synchronous version to avoid trigger the async handling which
  will cascade outside the scope of the synchronous intent of that test.
  • Loading branch information
metatoaster committed May 16, 2017
1 parent a869dbf commit 9da538b
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 1 deletion.
9 changes: 9 additions & 0 deletions src/nunja/engine.js
Expand Up @@ -111,6 +111,12 @@ Engine.prototype.init_element = function(element) {
if (main && main.init instanceof Function) {
main.init(element);
}
}, function() {
// TODO whether have this be a definable behavior, i.e. whether
// to leave undefine instead so import can be attempted again,
// or that it be hard-defined to be nothing like so:
// define(entry_point, [], {});
// requirejs.undef(entry_point);
});
};

Expand Down Expand Up @@ -164,11 +170,14 @@ Engine.prototype.populate = function (element, data, cb) {

if (!(cb instanceof Function)) {
element.innerHTML = this.render(mold_id, data);
this.init_element(element);
}
else {
var self = this;
this.render(mold_id, data, function(err, result) {
// TODO handle err if there is an error somewhere...
element.innerHTML = result;
self.init_element(element);
cb();
});
}
Expand Down
91 changes: 90 additions & 1 deletion src/nunja/tests/test_engine.js
Expand Up @@ -47,6 +47,7 @@ describe('nunja/engine simple test case', function() {
delete window.nunjucksPrecompiled['check/template.nja'];
requirejs.undef('text!check/template.nja');
requirejs.undef('text!dummy/mold/template.nja');
requirejs.undef('dummy/mold/index');
this.clock.restore();
document.body.innerHTML = "";
});
Expand Down Expand Up @@ -82,6 +83,56 @@ describe('nunja/engine simple test case', function() {
expect(this.engine.render('dummy/mold')).to.equal('dummy');
});

it('test simple populate, undefined index', function(done) {
document.body.innerHTML = '<div data-nunja="dummy/mold"></div>';
var element = $('div')[0];

define('text!dummy/mold/template.nja', [], function () {
return 'dummy';
});
require(['text!dummy/mold/template.nja'], function() {});
this.clock.tick(500);

// forcing an error import handling here to prevent requirejs
// from raising an exception after this execution was done by
// running the test within the error handler to ensure the
// error handler actually gets executed.
var self = this;
require(['dummy/mold/index'], function() {}, function() {
self.engine.populate(element, {});
self.clock.tick(500);
expect(document.body.innerHTML).to.equal(
'<div data-nunja="dummy/mold">dummy</div>');
done();
});
this.clock.tick(500);

});

it('test simple populate, defined index', function() {
document.body.innerHTML = '<div data-nunja="dummy/mold"></div>';
var element = $('div')[0];
var called = false;

// define modules
define('text!dummy/mold/template.nja', [], function () {
return 'dummy';
});
require(['text!dummy/mold/template.nja'], function() {});
define('dummy/mold/index', [], function () {
return {'init': function() {
called = true;
}};
});
require(['dummy/mold/index'], function() {});
this.clock.tick(500);
this.engine.populate(element, {});
this.clock.tick(500);
expect(document.body.innerHTML).to.equal(
'<div data-nunja="dummy/mold">dummy</div>');
expect(called).to.be.true;
});

});


Expand Down Expand Up @@ -148,6 +199,7 @@ describe_('nunja/engine async test case', function() {
requirejs.undef('text!mock.molds/populates/template.nja');
requirejs.undef('text!mock.molds/includes/template.nja');
requirejs.undef('text!mock.molds/includes/embedded.nja');
requirejs.undef('mock.molds/populate/index');
this.server.restore();
document.body.innerHTML = "";
});
Expand All @@ -171,9 +223,10 @@ describe_('nunja/engine async test case', function() {
});
});

it('test async include populate', function(done) {
it('test async include populate, no trigger', function(done) {
// Same as above, but it includes another template that required
// to be loaded.
// Note the lack of the index module.

// First set the innerHTML to a dummy rendering
document.body.innerHTML = (
Expand All @@ -188,6 +241,42 @@ describe_('nunja/engine async test case', function() {
});
});

it('test async populate trigger', function(done) {
// Given that the rendering for client side interactions almost
// always require async to be responsive, the populate method
// can and should function without the explicit load_mold like
// above.

var init_element;
var self = this;

// First set the innerHTML to a dummy rendering
document.body.innerHTML = (
'<div data-nunja="mock.molds/populate"></div>'
);
// Also define the module
define('mock.molds/populate/index', [], function() {
return {'init': function(el) {
init_element = el;
}};
});

// ensure the index module is first loaded to avoid async errors
require(['mock.molds/populate/index'], function() {
var element = $('div')[0];
self.engine.populate(element, {'msg': 'Hello World!'}, function() {
var text = element.innerHTML;
expect(text).to.equal(
'<span>nunja/engine populated: Hello World!</span>');
// DOM objects behave weird on assignment, so we cannot
// compare their identities directly.
expect(init_element.innerHTML).to.equal(
'<span>nunja/engine populated: Hello World!</span>');
done();
});
});
});

it('test async execute', function(done) {
this.engine.execute('mock.molds/includes', {}, function(err, text) {
expect(err).to.be.null;
Expand Down

0 comments on commit 9da538b

Please sign in to comment.