- add sources.
[platform/framework/web/crosswalk.git] / src / third_party / jstemplate / jstemplate_test.js
1 // Copyright 2006 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12 // implied. See the License for the specific language governing
13 // permissions and limitations under the License.
14 /**
15  * @author Steffen Meschkat (mesch@google.com)
16  * @fileoverview Unittest and examples for jstemplates.
17  */
18
19 function jstWrap(data, template) {
20   return jstProcess(new JsEvalContext(data), template);
21 }
22
23 function testJstSelect() {
24   // Template cardinality from jsselect.
25   var t = document.getElementById('t1');
26   var d = {
27     items: [ 'A', 'B', 'C', '' ]
28   }
29   jstWrap(d, t);
30
31   var h = t.innerHTML;
32   var clone = domCloneNode(t);
33   assertTrue(/>A<\/div>/.test(h));
34   assertTrue(/>B<\/div>/.test(h));
35   assertTrue(/>C<\/div>/.test(h));
36   assertTrue(/><\/div>/.test(h));
37
38   // Reprocessing with identical data.
39   jstWrap(d, t);
40   assertAttributesMatch(t, clone);
41
42   // Reprocessing with changed data.
43   d.items[1] = 'BB';
44   jstWrap(d, t);
45
46   h = t.innerHTML;
47   assertTrue(/>A<\/div>/.test(h));
48   assertFalse(/>B<\/div>/.test(h));
49   assertTrue(/>BB<\/div>/.test(h));
50   assertTrue(/>C<\/div>/.test(h));
51
52   // Reprocessing with dropped data.
53   d.items.pop();
54   d.items.pop();
55   jstWrap(d, t);
56   h = t.innerHTML;
57   assertTrue(/>A<\/div>/.test(h));
58   assertTrue(/>BB<\/div>/.test(h));
59   assertFalse(/>C<\/div>/.test(h));
60   assertFalse(/><\/div>/.test(h));
61
62   // Reprocessing with dropped data, once more.
63   d.items.pop();
64   jstWrap(d, t);
65   h = t.innerHTML;
66   assertTrue(/>A<\/div>/.test(h));
67   assertFalse(/>BB<\/div>/.test(h));
68   assertFalse(/>C<\/div>/.test(h));
69
70   // Reprocessing with empty data -- the last template instance is
71   // preserved, and only hidden.
72   d.items.pop();
73   jstWrap(d, t);
74
75   assertTrue(/>A<\/div>/.test(h));
76   assertFalse(/>BB<\/div>/.test(h));
77   assertFalse(/>C<\/div>/.test(h));
78
79   // Reprocessing with added data.
80   d.items.push('D');
81   jstWrap(d, t);
82   h = t.innerHTML;
83   assertFalse(/>A<\/div>/.test(h));
84   assertTrue(/>D<\/div>/.test(h));
85 }
86
87 function testJstDisplay() {
88   var t = document.getElementById('t2');
89   var d = {
90     display: true
91   }
92   jstWrap(d, t);
93
94   var h = t.innerHTML;
95   assertFalse(/display:\s*none/.test(h));
96
97   d.display = false;
98   jstWrap(d, t);
99
100   h = t.innerHTML;
101   assertTrue(/display:\s*none/.test(h));
102
103   // Check that 'this' within js expressions is the template node
104   t = document.getElementById('t2a');
105   d = {
106     showId: 'x'
107   };
108   jstWrap(d, t);
109
110   h = t.innerHTML;
111   assertFalse(/display:\s*none/.test(h));
112
113   d.showId = 'y';
114   jstWrap(d, t);
115
116   h = t.innerHTML;
117   assertTrue(/display:\s*none/.test(h));
118 }
119
120 function stringContains(str, sub) {
121   return str.indexOf(sub) != -1;
122 }
123
124 function testJseval() {
125   var data = {};
126
127   var counter = 0;
128   var ctx = new JsEvalContext(data);
129   ctx.setVariable("callback1", function() {
130     ++counter;
131   });
132   ctx.setVariable("callback2", function() {
133     counter *= 2;
134   });
135
136   jstProcess(ctx, document.getElementById('testJseval1'));
137   assertEquals("testJseval1", 1, counter);
138
139   jstProcess(ctx, document.getElementById('testJseval2'));
140   assertEquals("testJseval2", 4, counter);
141 }
142
143 function testJstValues() {
144   var t = document.getElementById('t3');
145   var d = {};
146   jstWrap(d, t);
147   var h = t.innerHTML;
148   assertTrue(stringContains(h, 'http://maps.google.com/'));
149   var t3a = document.getElementById('t3a');
150   assertEquals('http://maps.google.com/', t3a.foo.bar.baz);
151   assertEquals('http://maps.google.com/', t3a.bar);
152   assertEquals('red', t3a.style.backgroundColor);
153 }
154
155 function testJstTransclude() {
156   var t = document.getElementById('t4');
157   var p = document.getElementById('parent');
158   var d = {};
159   jstWrap(d, t);
160   var h = p.innerHTML;
161   assertTrue(h, stringContains(h, 'http://maps.google.com/'));
162 }
163
164 function assertAttributesMatch(first, second) {
165   assertEquals('assertAttributesMatch: number of child nodes',
166                jsLength(first.childNodes), jsLength(second.childNodes));
167   var b = second.firstChild;
168   for (var a = first.firstChild; a; a = a.nextSibling) {
169     var att = a.attributes;
170     if (att) {
171       assertTrue(b.attributes != null);
172       assertEquals('assertAttributesMatch: number of attribute nodes',
173                    att.length, b.attributes.length);
174       for (var i = 0; i < jsLength(att); i++) {
175         var a = att[i];
176         assertEquals('assertAttributesMatch: value of attribute ' + a.name,
177                      a.value, b.getAttribute(a.name));
178       }
179     } else {
180       assertNull(b.attributes);
181     }
182     b = b.nextSibling;
183   }
184 }
185
186 function testJsskip() {
187   var div = domCreateElement(document, "DIV");
188   div.innerHTML = [
189       '<div jseval="outercallback()" jsskip="1">',
190       '<div jseval="innercallback()">',
191       '</div>',
192       '</div>'
193   ].join('');
194
195   var data = {};
196   var ctx = new JsEvalContext(data);
197   var outerCalled = false;
198   ctx.setVariable("outercallback", function() {
199     outerCalled = true;
200   });
201   var innerCalled = false;
202   ctx.setVariable("innercallback", function() {
203     innerCalled = true;
204   });
205   jstProcess(ctx, div);
206
207   assertTrue(outerCalled);
208   assertFalse(innerCalled);
209 }
210
211 function testScalarContext() {
212   var t = document.getElementById('testScalarContext');
213
214   jstWrap(true, t);
215   assertTrue(/>true</.test(t.innerHTML));
216
217   jstWrap(false, t);
218   assertTrue(/>false</.test(t.innerHTML));
219
220   jstWrap(0, t);
221   assertTrue(/>0</.test(t.innerHTML));
222
223   jstWrap("foo", t);
224   assertTrue(/>foo</.test(t.innerHTML));
225
226   jstWrap(undefined, t);
227   assertTrue(/>undefined</.test(t.innerHTML));
228
229   jstWrap(null, t);
230   assertTrue(/>null</.test(t.innerHTML));
231 }
232
233 function testJstLoadTemplate() {
234   var wrapperId = 'testJstLoadTemplateWrapper';
235   var id = 'testJstLoadTemplate';
236   jstLoadTemplate_(document, '<div id="' + id + '">content</div>', wrapperId);
237   var wrapperElem = document.getElementById(wrapperId);
238   assertTrue('Expected wrapper element to be in document',
239              !!wrapperElem);
240   var newTemplate = document.getElementById(id);
241   assertTrue('Expected newly loaded template to be in document',
242              !!newTemplate);
243   assertTrue('Expected wrapper to be grandparent of template',
244              newTemplate.parentNode.parentNode == wrapperElem);
245
246   // Make sure the next template loaded with the same wrapper id re-uses the
247   // wrapper element.
248   var id2 = 'testJstLoadTemplate2';
249   jstLoadTemplate_(document, '<div id="' + id2 + '">content</div>', wrapperId);
250   var newTemplate2 = document.getElementById(id2);
251   assertTrue('Expected newly loaded template to be in document',
252              !!newTemplate2);
253   assertTrue('Expected wrapper to be grandparent of template',
254              newTemplate2.parentNode.parentNode == wrapperElem);
255 }
256
257 function testJstGetTemplateFromDom() {
258   var element;
259   // Get by id a template in the document
260   // Success
261   element = jstGetTemplate('t1');
262   assertTrue("Asserted jstGetTemplate('t1') to return a dom element",
263              !!element);
264   // Failure
265   element = jstGetTemplate('asdf');
266   assertFalse("Asserted jstGetTemplate('asdf') to return null",
267               !!element);
268 }
269
270 function testJstGetTemplateFromFunction() {
271   var element;
272   // Fetch a jstemplate by id from within a html string, passed via a function.
273   function returnHtmlWithId(id) {
274     var html =
275         '<div>' +
276         '<div id="' + id + '">Here is the template</div>' +
277         '</div>';
278     return html;
279   }
280   // Success
281   element = jstGetTemplate('template',
282                            partial(returnHtmlWithId, 'template'));
283   assertTrue("Expected jstGetTemplate('template') to return a dom element",
284              !!element);
285
286   // Failure
287   element = jstGetTemplate('asdf',
288                            partial(returnHtmlWithId, 'zxcv'));
289   assertFalse("Expected jstGetTemplate('zxcv') to return null",
290               !!element);
291 }
292
293 function testPrepareNode() {
294   var id, node;
295   // Reset the cache so we're testing from a known state.
296   JstProcessor.jstCache_ = {};
297   JstProcessor.jstCache_[0] = {};
298
299   // Skip pre-processed nodes.  Preprocessed nodes are those with a
300   // PROP_jstcache property.
301   var t = document.getElementById('t1');
302   var caches = [];
303   caches.push(JstProcessor.prepareNode_(t));
304   caches.push(JstProcessor.prepareNode_(t));
305   assertEquals('The same cache should be returned on each call to prepareNode',
306                caches[0], caches[1]);
307
308   // Preprocessing a node with a jst attribute should return a valid struct
309   id = 'testPrepareNodeWithAttributes';
310   jstLoadTemplate_(document, '<div id="' + id + '" jsskip="1"></div>');
311   node = document.getElementById(id);
312   var cache = JstProcessor.prepareNode_(node);
313   try {
314     var jsskip = cache['jsskip']({}, {});
315   } catch (e) {
316     fail('Exception when evaluating jsskip from cache');
317   }
318   assertEquals(1, jsskip);
319 }
320
321
322 function testPrepareNodeWithNoAttributes() {
323   // Preprocessing a node with no jst attributes should return null
324   var id = 'testPrepareNodeNoAttributes';
325   jstLoadTemplate_(document, '<div id="' + id + '"></div>');
326   var node = document.getElementById(id);
327   assertEquals('prepareNode with no jst attributes should return default',
328                JstProcessor.jstcache_[0], JstProcessor.prepareNode_(node));
329 }
330
331
332 function testJsVars() {
333   var template = document.createElement('div');
334   document.body.appendChild(template);
335   template.innerHTML = '<div jsvars="foo:\'foo\';bar:true;$baz:1"></div>';
336
337   var context = new JsEvalContext;
338   jstProcess(context, template);
339
340   assertEquals('foo', context.getVariable('foo'));
341   assertEquals(1, context.getVariable('$baz'));
342   assertTrue(context.getVariable('bar'));
343   assertUndefined(context.getVariable('foobar'));
344 }
345
346
347 function testCacheReuse() {
348   var template = document.createElement('div');
349   document.body.appendChild(template);
350   template.innerHTML = 
351     '<div jsvars="foo:\'foo\';bar:true;$baz:1"></div>' +
352     '<span jsvars="foo:\'foo\';bar:true;$baz:1"></span>';
353   JstProcessor.prepareTemplate_(template);
354   assertEquals(template.firstChild.getAttribute(ATT_jstcache),
355                template.lastChild.getAttribute(ATT_jstcache));
356 }