/* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ // Tests that the DOM Template engine works properly let tempScope = {}; Cu.import("resource:///modules/devtools/Templater.jsm", tempScope); Cu.import("resource:///modules/devtools/Promise.jsm", tempScope); let template = tempScope.template; let Promise = tempScope.Promise; function test() { addTab("http://example.com/browser/browser/devtools/shared/test/browser_templater_basic.html", function() { info("Starting DOM Templater Tests"); runTest(0); }); } function runTest(index) { var options = tests[index] = tests[index](); var holder = content.document.createElement('div'); holder.id = options.name; var body = content.document.body; body.appendChild(holder); holder.innerHTML = options.template; info('Running ' + options.name); template(holder, options.data, options.options); if (typeof options.result == 'string') { is(holder.innerHTML, options.result, options.name); } else { ok(holder.innerHTML.match(options.result), options.name); } if (options.also) { options.also(options); } function runNextTest() { index++; if (index < tests.length) { runTest(index); } else { finished(); } } if (options.later) { var ais = is.bind(this); function createTester(holder, options) { return function() { ais(holder.innerHTML, options.later, options.name + ' later'); runNextTest(); }.bind(this); } executeSoon(createTester(holder, options)); } else { runNextTest(); } } function finished() { gBrowser.removeCurrentTab(); info("Finishing DOM Templater Tests"); tests = null; finish(); } /** * Why have an array of functions that return data rather than just an array * of the data itself? Some of these tests contain calls to delayReply() which * sets up async processing using executeSoon(). Since the execution of these * tests is asynchronous, the delayed reply will probably arrive before the * test is executed, making the test be synchronous. So we wrap the data in a * function so we only set it up just before we use it. */ var tests = [ function() { return { name: 'simpleNesting', template: '
hello ${name}
', options: { allowEval: true }, data: { name: 'fred' }, result: 'hello fred
' };}, function() { return { name: 'ifFalse', template: 'hello ${name}
', options: { allowEval: true }, data: { name: 'jim' }, result: '' };}, function() { return { name: 'simpleLoop', template: '${index}
', options: { allowEval: true }, data: {}, result: '1
2
3
' };}, function() { return { name: 'loopElement', template: '${name}
', data: { name: 'pass 8' }, result: 'pass 8
', also: function(options) { ok(options.data.element.innerHTML, 'pass 9', 'saveElement saved'); delete options.data.element; } };}, function() { return { name: 'useElement', template: '${adjust(__element)}
', options: { allowEval: true }, data: { adjust: function(element) { is('pass9', element.id, 'useElement adjust'); return 'pass 9b' } }, result: 'pass 9b
' };}, function() { return { name: 'asyncInline', template: '${delayed}', data: { delayed: delayReply('inline') }, result: '', later: 'inline' };}, // Bug 692028: DOMTemplate memory leak with asynchronous arrays function() { return { name: 'asyncArray', template: '${i}
', data: { delayed: delayReply([1, 2, 3]) }, result: '', later: '1
2
3
' };}, function() { return { name: 'asyncMember', template: '${i}
', data: { delayed: [delayReply(4), delayReply(5), delayReply(6)] }, result: '', later: '4
5
6
' };}, // Bug 692028: DOMTemplate memory leak with asynchronous arrays function() { return { name: 'asyncBoth', template: '${i}
', data: { delayed: delayReply([ delayReply(4), delayReply(5), delayReply(6) ]) }, result: '', later: '4
5
6
' };}, // Bug 701762: DOMTemplate fails when ${foo()} returns undefined function() { return { name: 'functionReturningUndefiend', template: '${foo()}
', options: { allowEval: true }, data: { foo: function() {} }, result: 'undefined
' };}, // Bug 702642: DOMTemplate is relatively slow when evaluating JS ${} function() { return { name: 'propertySimple', template: '${a.b.c}
', data: { a: { b: { c: 'hello' } } }, result: 'hello
' };}, function() { return { name: 'propertyPass', template: '${Math.max(1, 2)}
', options: { allowEval: true }, result: '2
' };}, function() { return { name: 'propertyFail', template: '${Math.max(1, 2)}
', result: '${Math.max(1, 2)}
' };} ]; function delayReply(data) { var p = new Promise(); executeSoon(function() { p.resolve(data); }); return p; }