browser/devtools/shared/test/browser_templater_basic.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* Any copyright is dedicated to the Public Domain.
michael@0 2 http://creativecommons.org/publicdomain/zero/1.0/ */
michael@0 3
michael@0 4 // Tests that the DOM Template engine works properly
michael@0 5
michael@0 6 /*
michael@0 7 * These tests run both in Mozilla/Mochitest and plain browsers (as does
michael@0 8 * domtemplate)
michael@0 9 * We should endevour to keep the source in sync.
michael@0 10 */
michael@0 11
michael@0 12 var promise = Cu.import("resource://gre/modules/devtools/deprecated-sync-thenables.js", {}).Promise;
michael@0 13 var template = Cu.import("resource://gre/modules/devtools/Templater.jsm", {}).template;
michael@0 14
michael@0 15 const TEST_URI = "http://example.com/browser/browser/devtools/shared/test/browser_templater_basic.html";
michael@0 16
michael@0 17 function test() {
michael@0 18 addTab(TEST_URI, function() {
michael@0 19 info("Starting DOM Templater Tests");
michael@0 20 runTest(0);
michael@0 21 });
michael@0 22 }
michael@0 23
michael@0 24 function runTest(index) {
michael@0 25 var options = tests[index] = tests[index]();
michael@0 26 var holder = content.document.createElement('div');
michael@0 27 holder.id = options.name;
michael@0 28 var body = content.document.body;
michael@0 29 body.appendChild(holder);
michael@0 30 holder.innerHTML = options.template;
michael@0 31
michael@0 32 info('Running ' + options.name);
michael@0 33 template(holder, options.data, options.options);
michael@0 34
michael@0 35 if (typeof options.result == 'string') {
michael@0 36 is(holder.innerHTML, options.result, options.name);
michael@0 37 }
michael@0 38 else {
michael@0 39 ok(holder.innerHTML.match(options.result) != null,
michael@0 40 options.name + ' result=\'' + holder.innerHTML + '\'');
michael@0 41 }
michael@0 42
michael@0 43 if (options.also) {
michael@0 44 options.also(options);
michael@0 45 }
michael@0 46
michael@0 47 function runNextTest() {
michael@0 48 index++;
michael@0 49 if (index < tests.length) {
michael@0 50 runTest(index);
michael@0 51 }
michael@0 52 else {
michael@0 53 finished();
michael@0 54 }
michael@0 55 }
michael@0 56
michael@0 57 if (options.later) {
michael@0 58 var ais = is.bind(this);
michael@0 59
michael@0 60 function createTester(holder, options) {
michael@0 61 return function() {
michael@0 62 ais(holder.innerHTML, options.later, options.name + ' later');
michael@0 63 runNextTest();
michael@0 64 }.bind(this);
michael@0 65 }
michael@0 66
michael@0 67 executeSoon(createTester(holder, options));
michael@0 68 }
michael@0 69 else {
michael@0 70 runNextTest();
michael@0 71 }
michael@0 72 }
michael@0 73
michael@0 74 function finished() {
michael@0 75 gBrowser.removeCurrentTab();
michael@0 76 info("Finishing DOM Templater Tests");
michael@0 77 tests = null;
michael@0 78 finish();
michael@0 79 }
michael@0 80
michael@0 81 /**
michael@0 82 * Why have an array of functions that return data rather than just an array
michael@0 83 * of the data itself? Some of these tests contain calls to delayReply() which
michael@0 84 * sets up async processing using executeSoon(). Since the execution of these
michael@0 85 * tests is asynchronous, the delayed reply will probably arrive before the
michael@0 86 * test is executed, making the test be synchronous. So we wrap the data in a
michael@0 87 * function so we only set it up just before we use it.
michael@0 88 */
michael@0 89 var tests = [
michael@0 90 function() { return {
michael@0 91 name: 'simpleNesting',
michael@0 92 template: '<div id="ex1">${nested.value}</div>',
michael@0 93 data: { nested:{ value:'pass 1' } },
michael@0 94 result: '<div id="ex1">pass 1</div>'
michael@0 95 };},
michael@0 96
michael@0 97 function() { return {
michael@0 98 name: 'returnDom',
michael@0 99 template: '<div id="ex2">${__element.ownerDocument.createTextNode(\'pass 2\')}</div>',
michael@0 100 options: { allowEval: true },
michael@0 101 data: {},
michael@0 102 result: '<div id="ex2">pass 2</div>'
michael@0 103 };},
michael@0 104
michael@0 105 function() { return {
michael@0 106 name: 'srcChange',
michael@0 107 template: '<img _src="${fred}" id="ex3">',
michael@0 108 data: { fred:'green.png' },
michael@0 109 result: /<img( id="ex3")? src="green.png"( id="ex3")?>/
michael@0 110 };},
michael@0 111
michael@0 112 function() { return {
michael@0 113 name: 'ifTrue',
michael@0 114 template: '<p if="${name !== \'jim\'}">hello ${name}</p>',
michael@0 115 options: { allowEval: true },
michael@0 116 data: { name: 'fred' },
michael@0 117 result: '<p>hello fred</p>'
michael@0 118 };},
michael@0 119
michael@0 120 function() { return {
michael@0 121 name: 'ifFalse',
michael@0 122 template: '<p if="${name !== \'jim\'}">hello ${name}</p>',
michael@0 123 options: { allowEval: true },
michael@0 124 data: { name: 'jim' },
michael@0 125 result: ''
michael@0 126 };},
michael@0 127
michael@0 128 function() { return {
michael@0 129 name: 'simpleLoop',
michael@0 130 template: '<p foreach="index in ${[ 1, 2, 3 ]}">${index}</p>',
michael@0 131 options: { allowEval: true },
michael@0 132 data: {},
michael@0 133 result: '<p>1</p><p>2</p><p>3</p>'
michael@0 134 };},
michael@0 135
michael@0 136 function() { return {
michael@0 137 name: 'loopElement',
michael@0 138 template: '<loop foreach="i in ${array}">${i}</loop>',
michael@0 139 data: { array: [ 1, 2, 3 ] },
michael@0 140 result: '123'
michael@0 141 };},
michael@0 142
michael@0 143 // Bug 692028: DOMTemplate memory leak with asynchronous arrays
michael@0 144 // Bug 692031: DOMTemplate async loops do not drop the loop element
michael@0 145 function() { return {
michael@0 146 name: 'asyncLoopElement',
michael@0 147 template: '<loop foreach="i in ${array}">${i}</loop>',
michael@0 148 data: { array: delayReply([1, 2, 3]) },
michael@0 149 result: '<span></span>',
michael@0 150 later: '123'
michael@0 151 };},
michael@0 152
michael@0 153 function() { return {
michael@0 154 name: 'saveElement',
michael@0 155 template: '<p save="${element}">${name}</p>',
michael@0 156 data: { name: 'pass 8' },
michael@0 157 result: '<p>pass 8</p>',
michael@0 158 also: function(options) {
michael@0 159 ok(options.data.element.innerHTML, 'pass 9', 'saveElement saved');
michael@0 160 delete options.data.element;
michael@0 161 }
michael@0 162 };},
michael@0 163
michael@0 164 function() { return {
michael@0 165 name: 'useElement',
michael@0 166 template: '<p id="pass9">${adjust(__element)}</p>',
michael@0 167 options: { allowEval: true },
michael@0 168 data: {
michael@0 169 adjust: function(element) {
michael@0 170 is('pass9', element.id, 'useElement adjust');
michael@0 171 return 'pass 9b'
michael@0 172 }
michael@0 173 },
michael@0 174 result: '<p id="pass9">pass 9b</p>'
michael@0 175 };},
michael@0 176
michael@0 177 function() { return {
michael@0 178 name: 'asyncInline',
michael@0 179 template: '${delayed}',
michael@0 180 data: { delayed: delayReply('inline') },
michael@0 181 result: '<span></span>',
michael@0 182 later: 'inline'
michael@0 183 };},
michael@0 184
michael@0 185 // Bug 692028: DOMTemplate memory leak with asynchronous arrays
michael@0 186 function() { return {
michael@0 187 name: 'asyncArray',
michael@0 188 template: '<p foreach="i in ${delayed}">${i}</p>',
michael@0 189 data: { delayed: delayReply([1, 2, 3]) },
michael@0 190 result: '<span></span>',
michael@0 191 later: '<p>1</p><p>2</p><p>3</p>'
michael@0 192 };},
michael@0 193
michael@0 194 function() { return {
michael@0 195 name: 'asyncMember',
michael@0 196 template: '<p foreach="i in ${delayed}">${i}</p>',
michael@0 197 data: { delayed: [delayReply(4), delayReply(5), delayReply(6)] },
michael@0 198 result: '<span></span><span></span><span></span>',
michael@0 199 later: '<p>4</p><p>5</p><p>6</p>'
michael@0 200 };},
michael@0 201
michael@0 202 // Bug 692028: DOMTemplate memory leak with asynchronous arrays
michael@0 203 function() { return {
michael@0 204 name: 'asyncBoth',
michael@0 205 template: '<p foreach="i in ${delayed}">${i}</p>',
michael@0 206 data: {
michael@0 207 delayed: delayReply([
michael@0 208 delayReply(4),
michael@0 209 delayReply(5),
michael@0 210 delayReply(6)
michael@0 211 ])
michael@0 212 },
michael@0 213 result: '<span></span>',
michael@0 214 later: '<p>4</p><p>5</p><p>6</p>'
michael@0 215 };},
michael@0 216
michael@0 217 // Bug 701762: DOMTemplate fails when ${foo()} returns undefined
michael@0 218 function() { return {
michael@0 219 name: 'functionReturningUndefiend',
michael@0 220 template: '<p>${foo()}</p>',
michael@0 221 options: { allowEval: true },
michael@0 222 data: {
michael@0 223 foo: function() {}
michael@0 224 },
michael@0 225 result: '<p>undefined</p>'
michael@0 226 };},
michael@0 227
michael@0 228 // Bug 702642: DOMTemplate is relatively slow when evaluating JS ${}
michael@0 229 function() { return {
michael@0 230 name: 'propertySimple',
michael@0 231 template: '<p>${a.b.c}</p>',
michael@0 232 data: { a: { b: { c: 'hello' } } },
michael@0 233 result: '<p>hello</p>'
michael@0 234 };},
michael@0 235
michael@0 236 function() { return {
michael@0 237 name: 'propertyPass',
michael@0 238 template: '<p>${Math.max(1, 2)}</p>',
michael@0 239 options: { allowEval: true },
michael@0 240 result: '<p>2</p>'
michael@0 241 };},
michael@0 242
michael@0 243 function() { return {
michael@0 244 name: 'propertyFail',
michael@0 245 template: '<p>${Math.max(1, 2)}</p>',
michael@0 246 result: '<p>${Math.max(1, 2)}</p>'
michael@0 247 };},
michael@0 248
michael@0 249 // Bug 723431: DOMTemplate should allow customisation of display of
michael@0 250 // null/undefined values
michael@0 251 function() { return {
michael@0 252 name: 'propertyUndefAttrFull',
michael@0 253 template: '<p>${nullvar}|${undefinedvar1}|${undefinedvar2}</p>',
michael@0 254 data: { nullvar: null, undefinedvar1: undefined },
michael@0 255 result: '<p>null|undefined|undefined</p>'
michael@0 256 };},
michael@0 257
michael@0 258 function() { return {
michael@0 259 name: 'propertyUndefAttrBlank',
michael@0 260 template: '<p>${nullvar}|${undefinedvar1}|${undefinedvar2}</p>',
michael@0 261 data: { nullvar: null, undefinedvar1: undefined },
michael@0 262 options: { blankNullUndefined: true },
michael@0 263 result: '<p>||</p>'
michael@0 264 };},
michael@0 265
michael@0 266 function() { return {
michael@0 267 name: 'propertyUndefAttrFull',
michael@0 268 template: '<div><p value="${nullvar}"></p><p value="${undefinedvar1}"></p><p value="${undefinedvar2}"></p></div>',
michael@0 269 data: { nullvar: null, undefinedvar1: undefined },
michael@0 270 result: '<div><p value="null"></p><p value="undefined"></p><p value="undefined"></p></div>'
michael@0 271 };},
michael@0 272
michael@0 273 function() { return {
michael@0 274 name: 'propertyUndefAttrBlank',
michael@0 275 template: '<div><p value="${nullvar}"></p><p value="${undefinedvar1}"></p><p value="${undefinedvar2}"></p></div>',
michael@0 276 data: { nullvar: null, undefinedvar1: undefined },
michael@0 277 options: { blankNullUndefined: true },
michael@0 278 result: '<div><p value=""></p><p value=""></p><p value=""></p></div>'
michael@0 279 };}
michael@0 280 ];
michael@0 281
michael@0 282 function delayReply(data) {
michael@0 283 var d = promise.defer();
michael@0 284 executeSoon(function() {
michael@0 285 d.resolve(data);
michael@0 286 });
michael@0 287 return d.promise;
michael@0 288 }

mercurial