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