/* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ "use strict"; // Tests that the DOM Template engine works properly /* * These tests run both in Mozilla/Mochitest and plain browsers (as does * domtemplate) * We should endevour to keep the source in sync. */ const {template} = require("devtools/shared/gcli/templater"); const TEST_URI = TEST_URI_ROOT + "browser_templater_basic.html"; var test = Task.async(function* () { yield addTab("about:blank"); let [host,, doc] = yield createHost("bottom", TEST_URI); info("Starting DOM Templater Tests"); runTest(0, host, doc); }); function runTest(index, host, doc) { let options = tests[index] = tests[index](); let holder = doc.createElement("div"); holder.id = options.name; let body = doc.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) != null, options.name + " result='" + holder.innerHTML + "'"); } if (options.also) { options.also(options); } function runNextTest() { index++; if (index < tests.length) { runTest(index, host, doc); } else { finished(host); } } if (options.later) { let ais = is.bind(this); function createTester(testHolder, testOptions) { return () => { ais(testHolder.innerHTML, testOptions.later, testOptions.name + " later"); runNextTest(); }; } executeSoon(createTester(holder, options)); } else { runNextTest(); } } function finished(host) { host.destroy(); 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 = [ () => ({ name: "simpleNesting", template: '
hello ${name}
', options: { allowEval: true }, data: { name: "fred" }, result: "hello fred
" }), () => ({ name: "ifFalse", template: 'hello ${name}
', options: { allowEval: true }, data: { name: "jim" }, result: "" }), () => ({ name: "simpleLoop", template: '${index}
', options: { allowEval: true }, data: {}, result: "1
2
3
" }), () => ({ 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; } }), () => ({ name: "useElement", template: '${adjust(__element)}
', options: { allowEval: true }, data: { adjust: function (element) { is("pass9", element.id, "useElement adjust"); return "pass 9b"; } }, result: 'pass 9b
' }), () => ({ name: "asyncInline", template: "${delayed}", data: { delayed: delayReply("inline") }, result: "", later: "inline" }), // Bug 692028: DOMTemplate memory leak with asynchronous arrays () => ({ name: "asyncArray", template: '${i}
', data: { delayed: delayReply([1, 2, 3]) }, result: "", later: "1
2
3
" }), () => ({ 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 () => ({ 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 () => ({ name: "functionReturningUndefiend", template: "${foo()}
", options: { allowEval: true }, data: { foo: function () {} }, result: "undefined
" }), // Bug 702642: DOMTemplate is relatively slow when evaluating JS ${} () => ({ name: "propertySimple", template: "${a.b.c}
", data: { a: { b: { c: "hello" } } }, result: "hello
" }), () => ({ name: "propertyPass", template: "${Math.max(1, 2)}
", options: { allowEval: true }, result: "2
" }), () => ({ name: "propertyFail", template: "${Math.max(1, 2)}
", result: "${Math.max(1, 2)}
" }), // Bug 723431: DOMTemplate should allow customisation of display of // null/undefined values () => ({ name: "propertyUndefAttrFull", template: "${nullvar}|${undefinedvar1}|${undefinedvar2}
", data: { nullvar: null, undefinedvar1: undefined }, result: "null|undefined|undefined
" }), () => ({ name: "propertyUndefAttrBlank", template: "${nullvar}|${undefinedvar1}|${undefinedvar2}
", data: { nullvar: null, undefinedvar1: undefined }, options: { blankNullUndefined: true }, result: "||
" }), /* eslint-disable max-len */ () => ({ name: "propertyUndefAttrFull", template: '