]>
Commit | Line | Data |
---|---|---|
6527f429 DM |
1 | describe("Ext.XTemplate", function() {\r |
2 | var tpl,\r | |
3 | data,\r | |
4 | arrayData,\r | |
5 | objectData;\r | |
6 | \r | |
7 | beforeEach(function() {\r | |
8 | data = {\r | |
9 | name: "Nicolas Ferrero",\r | |
10 | title: "Developer",\r | |
11 | company: "Sencha",\r | |
12 | email: "nico@sencha.com",\r | |
13 | address: "10 Rue St Ferreol",\r | |
14 | city: "Toulouse",\r | |
15 | country: "France",\r | |
16 | zip: "31000",\r | |
17 | drinks: ["Wine", "Coffee", "Corona"],\r | |
18 | something: {\r | |
19 | name: "root",\r | |
20 | child : {\r | |
21 | name: "child"\r | |
22 | }\r | |
23 | },\r | |
24 | kids: [{\r | |
25 | name: "Joshua",\r | |
26 | age:3\r | |
27 | },{\r | |
28 | name: "Nina",\r | |
29 | age:2\r | |
30 | },{\r | |
31 | name: "Solomon",\r | |
32 | age:0\r | |
33 | }],\r | |
34 | computers: [{\r | |
35 | cpu: "2Ghz",\r | |
36 | hdd: "1To"\r | |
37 | },{\r | |
38 | cpu: "100Mhz",\r | |
39 | hdd: "500Mo"\r | |
40 | }]\r | |
41 | };\r | |
42 | arrayData = {\r | |
43 | arrays: [\r | |
44 | [ { name: 'Item A1' }, { name: 'Item A2' } ],\r | |
45 | [ { name: 'Item B1' }, { name: 'Item B2' } ]\r | |
46 | ]\r | |
47 | };\r | |
48 | objectData = {\r | |
49 | a: 'aValue',\r | |
50 | b: {\r | |
51 | x: 'xValue',\r | |
52 | y: 'yValue'\r | |
53 | },\r | |
54 | c: 'cValue'\r | |
55 | };\r | |
56 | \r | |
57 | });\r | |
58 | \r | |
59 | describe("instantiation", function() {\r | |
60 | it("should extend Ext.Template", function() {\r | |
61 | tpl = new Ext.XTemplate("");\r | |
62 | \r | |
63 | expect(tpl.superclass).toEqual(Ext.Template.prototype);\r | |
64 | });\r | |
65 | \r | |
66 | it("should alias apply with applyTemplate", function() {\r | |
67 | tpl = new Ext.XTemplate("");\r | |
68 | \r | |
69 | spyOn(tpl, 'apply');\r | |
70 | \r | |
71 | tpl.applyTemplate();\r | |
72 | \r | |
73 | expect(tpl.apply).toHaveBeenCalled();\r | |
74 | });\r | |
75 | \r | |
76 | it("should compile on first use", function() {\r | |
77 | tpl = new Ext.XTemplate('Hello {foo}');\r | |
78 | expect(tpl.fn).toBe(null);\r | |
79 | \r | |
80 | var s = tpl.apply({ foo: 42 });\r | |
81 | expect(s).toBe('Hello 42');\r | |
82 | expect(typeof tpl.fn).toBe('function');\r | |
83 | });\r | |
84 | \r | |
85 | /* begin this line with "//* to include this test or "/*" to remove it\r | |
86 | it('should perform better', function () {\r | |
87 | function run (name) {\r | |
88 | var T = Ext[name],\r | |
89 | t0 = new Date().getTime(),\r | |
90 | K = 2000,\r | |
91 | t, s;\r | |
92 | \r | |
93 | for (var i = 0; i < K; ++i) {\r | |
94 | t = new T(\r | |
95 | '<p>Name: {name}</p>',\r | |
96 | '<p>Kids: ',\r | |
97 | '<tpl for="kids">',\r | |
98 | '<tpl if="age > 1">',\r | |
99 | '<p>{name}</p>',\r | |
100 | '<p>Dad: {parent.name}</p>',\r | |
101 | '</tpl>',\r | |
102 | '</tpl></p>'\r | |
103 | );\r | |
104 | }\r | |
105 | \r | |
106 | var t1 = new Date().getTime();\r | |
107 | \r | |
108 | for (i = 0; i < K; ++i) {\r | |
109 | s = t.apply(data);\r | |
110 | }\r | |
111 | \r | |
112 | var t2 = new Date().getTime();\r | |
113 | \r | |
114 | for (i = 0; i < K; ++i) {\r | |
115 | t = new T(\r | |
116 | '<p>Name: {name}</p>',\r | |
117 | '<p>Kids: ',\r | |
118 | '<tpl for="kids">',\r | |
119 | '<tpl if="age > 1">',\r | |
120 | '<p>{name}</p>',\r | |
121 | '<p>Dad: {parent.name}</p>',\r | |
122 | '</tpl>',\r | |
123 | '</tpl></p>'\r | |
124 | );\r | |
125 | s = t.apply(data);\r | |
126 | }\r | |
127 | \r | |
128 | var t3 = new Date().getTime();\r | |
129 | \r | |
130 | Ext.log(name + ': total=' + (t2 - t0)/K + ' ctor=' + (t1 - t0)/K +\r | |
131 | ' apply=' + (t2 - t1)/K + ' ctorApply=' + (t3 - t2)/K);\r | |
132 | }\r | |
133 | \r | |
134 | run('XTemplate');\r | |
135 | run('XTemplate1');\r | |
136 | run('XTemplate2');\r | |
137 | });/**/\r | |
138 | });\r | |
139 | \r | |
140 | describe("tags", function() {\r | |
141 | describe("if", function() {\r | |
142 | it("should handle tpl tag with no attributes", function() {\r | |
143 | tpl = new Ext.XTemplate(\r | |
144 | '<tpl>{name}</tpl>'\r | |
145 | );\r | |
146 | expect(tpl.apply({name: 'Phil'})).toEqual('Phil');\r | |
147 | });\r | |
148 | it('should handle <tpl if=""> like <tpl>', function() {\r | |
149 | tpl = new Ext.XTemplate(\r | |
150 | '<p>Kids: ',\r | |
151 | '<tpl if="">',\r | |
152 | '<p>{name}</p>',\r | |
153 | '</tpl></p>'\r | |
154 | );\r | |
155 | \r | |
156 | expect(tpl.apply(data.kids)).toEqual('<p>Kids: <p></p></p>');\r | |
157 | });\r | |
158 | \r | |
159 | it('should handle if, elif and else', function() {\r | |
160 | tpl = new Ext.XTemplate(\r | |
161 | '<tpl for=\'kids\'>',\r | |
162 | '<tpl if="age > 2">',\r | |
163 | '<p>{name}</p>',\r | |
164 | '<p>Pops: {parent.name}</p>',\r | |
165 | '<tpl elif="age > 1">',\r | |
166 | '<p>{name}</p>',\r | |
167 | '<p>Dad: {parent.name}</p>',\r | |
168 | '<tpl else>',\r | |
169 | '<p>{name}</p>',\r | |
170 | '<p>Daddy: {parent.name}</p>',\r | |
171 | '</tpl>',\r | |
172 | '</tpl><p>!</p>'\r | |
173 | );\r | |
174 | \r | |
175 | var s = tpl.apply(data);\r | |
176 | expect(s).toEqual('<p>Joshua</p><p>Pops: Nicolas Ferrero</p>' +\r | |
177 | '<p>Nina</p><p>Dad: Nicolas Ferrero</p>' +\r | |
178 | '<p>Solomon</p><p>Daddy: Nicolas Ferrero</p><p>!</p>');\r | |
179 | });\r | |
180 | \r | |
181 | it('should handle verbatim block', function() {\r | |
182 | tpl = new Ext.XTemplate(\r | |
183 | '<tpl for=\'kids\'>',\r | |
184 | '<tpl if="age >= 3">',\r | |
185 | '{% continue; %}',\r | |
186 | '</tpl>',\r | |
187 | '<tpl if="this.count">',\r | |
188 | ' and ',\r | |
189 | '</tpl>',\r | |
190 | '{% ++this.count %}',\r | |
191 | '{name} is less than 3',\r | |
192 | '</tpl>!!!',\r | |
193 | {\r | |
194 | count: 0\r | |
195 | }\r | |
196 | );\r | |
197 | \r | |
198 | var s = tpl.apply(data);\r | |
199 | expect(s).toEqual('Nina is less than 3 and Solomon is less than 3!!!');\r | |
200 | });\r | |
201 | \r | |
202 | it('should handle verbatim if/else', function() {\r | |
203 | tpl = new Ext.XTemplate(\r | |
204 | '<tpl for=\'kids\'>',\r | |
205 | '{% if (values.age >= 3) { %}',\r | |
206 | '{% continue; %}',\r | |
207 | '{% }',\r | |
208 | 'if (this.count) { %}',\r | |
209 | ' and ',\r | |
210 | '{% } %}',\r | |
211 | '{% ++this.count %}',\r | |
212 | '{name} is less than 3',\r | |
213 | '</tpl>!!!',\r | |
214 | {\r | |
215 | count: 0\r | |
216 | }\r | |
217 | );\r | |
218 | \r | |
219 | var s = tpl.apply(data);\r | |
220 | expect(s).toEqual('Nina is less than 3 and Solomon is less than 3!!!');\r | |
221 | });\r | |
222 | \r | |
223 | it('should handle double quotes', function() {\r | |
224 | tpl = new Ext.XTemplate(\r | |
225 | "<tpl for='kids'>",\r | |
226 | "<tpl if='name==\"Joshua\"'>",\r | |
227 | "Josh",\r | |
228 | "<tpl else>",\r | |
229 | " {name}",\r | |
230 | "</tpl>",\r | |
231 | '</tpl>!!!'\r | |
232 | );\r | |
233 | \r | |
234 | var s = tpl.apply(data);\r | |
235 | expect(s).toEqual('Josh Nina Solomon!!!');\r | |
236 | });\r | |
237 | \r | |
238 | // From http://www.sencha.com/forum/showthread.php?142918\r | |
239 | it('should handle single quotes', function () {\r | |
240 | tpl = new Ext.XTemplate(\r | |
241 | '<tpl for=".">',\r | |
242 | '<div class="dv-grup-body">',\r | |
243 | '<tpl for="menus">',\r | |
244 | '<div class="dv-element small" id="{id}" test="{test}" sample="{sample}" cmpName="{cmpName}">',\r | |
245 | '<span>',\r | |
246 | '<img src="img/icons/{icon}.png" title="{name}" align="left">',\r | |
247 | '<tpl if="values.test * values.sample == 0">',\r | |
248 | '<img src="img/icons/warning.png" align="right" title="{[ values.sample == 0 ? \'Sample Text 1\' : \'Sample Text 2\' ]}">',\r | |
249 | '</tpl>',\r | |
250 | '<span class="boldText" style="float:left;">',\r | |
251 | '{name}',\r | |
252 | '</span>',\r | |
253 | '</span>',\r | |
254 | '</div>',\r | |
255 | '</tpl>',\r | |
256 | '</div>',\r | |
257 | '</tpl>');\r | |
258 | \r | |
259 | var s = tpl.apply({\r | |
260 | menus: [\r | |
261 | { id: 'foo', test: 0, sample: 3, cmpName: 'cname', name: 'Name', icon: 'ico' }\r | |
262 | ]\r | |
263 | });\r | |
264 | expect(s).toEqual('<div class="dv-grup-body">'+\r | |
265 | '<div class="dv-element small" id="foo" test="0" sample="3" cmpName="cname">'+\r | |
266 | '<span>'+\r | |
267 | '<img src="img/icons/ico.png" title="Name" align="left">'+\r | |
268 | '<img src="img/icons/warning.png" align="right" title="Sample Text 2">'+\r | |
269 | '<span class="boldText" style="float:left;">'+\r | |
270 | 'Name'+\r | |
271 | '</span>'+\r | |
272 | '</span>'+\r | |
273 | '</div></div>'\r | |
274 | );\r | |
275 | });\r | |
276 | });\r | |
277 | \r | |
278 | describe("switch", function() {\r | |
279 | it('should handle switch, case and default with numbers', function() {\r | |
280 | tpl = new Ext.XTemplate(\r | |
281 | '<tpl for=\'kids\'>',\r | |
282 | '<tpl switch="age">',\r | |
283 | '<tpl case="3" case="4">',\r | |
284 | '<p>{name} is 3...</p>',\r | |
285 | '<tpl case="2">',\r | |
286 | '<p>{name} is 2...</p>',\r | |
287 | '<tpl default>',\r | |
288 | '<p>{name} is {age}!</p>',\r | |
289 | '</tpl>',\r | |
290 | '</tpl><p>!</p>'\r | |
291 | );\r | |
292 | \r | |
293 | var s = tpl.apply(data);\r | |
294 | expect(s).toEqual('<p>Joshua is 3...</p><p>Nina is 2...</p><p>Solomon is 0!</p><p>!</p>');\r | |
295 | });\r | |
296 | \r | |
297 | it('should handle switch, case and default with strings', function() {\r | |
298 | tpl = new Ext.XTemplate(\r | |
299 | '<tpl for=\'kids\'>',\r | |
300 | '<tpl switch="name">',\r | |
301 | '<tpl case="Joshua" case="Solomon">',\r | |
302 | '<p>{name} is a boy</p>',\r | |
303 | '<tpl default>',\r | |
304 | '<p>{name} is a girl!</p>',\r | |
305 | '</tpl>',\r | |
306 | '</tpl><p>!</p>'\r | |
307 | );\r | |
308 | \r | |
309 | var s = tpl.apply(data);\r | |
310 | expect(s).toEqual('<p>Joshua is a boy</p><p>Nina is a girl!</p><p>Solomon is a boy</p><p>!</p>');\r | |
311 | });\r | |
312 | \r | |
313 | it("should be able to switch on xindex", function() {\r | |
314 | tpl = new Ext.XTemplate([\r | |
315 | '<tpl for=".">',\r | |
316 | '<tpl switch="#">',\r | |
317 | '<tpl case="1">One',\r | |
318 | '<tpl case="2">Two',\r | |
319 | '<tpl case="3">Three',\r | |
320 | '<tpl case="4">Four',\r | |
321 | '<tpl default>Bigger',\r | |
322 | '</tpl>',\r | |
323 | '</tpl>']);\r | |
324 | \r | |
325 | expect(tpl.apply([1, 2, 3, 4, 5, 6])).toBe('OneTwoThreeFourBiggerBigger');\r | |
326 | });\r | |
327 | \r | |
328 | it("should allow spaces after the switch", function() {\r | |
329 | tpl = new Ext.XTemplate('<tpl switch="foo"> <tpl case="bar">bar</tpl>');\r | |
330 | expect(tpl.apply({\r | |
331 | foo: 'bar'\r | |
332 | })).toBe('bar');\r | |
333 | });\r | |
334 | });\r | |
335 | \r | |
336 | describe("for", function () {\r | |
337 | it('should examine the data object provided if for="." is specified (include array index test)', function() {\r | |
338 | tpl = new Ext.XTemplate(\r | |
339 | '<p>Kids: ',\r | |
340 | '<tpl for=".">',\r | |
341 | '<p>{#}. {name}</p>',\r | |
342 | '</tpl></p>'\r | |
343 | );\r | |
344 | var s = tpl.apply(data.kids);\r | |
345 | expect(s).toEqual('<p>Kids: <p>1. Joshua</p><p>2. Nina</p><p>3. Solomon</p></p>');\r | |
346 | });\r | |
347 | \r | |
348 | it('should insert "between" values', function() {\r | |
349 | tpl = new Ext.XTemplate(\r | |
350 | '<p>Kids: ',\r | |
351 | '<tpl for="." between=",">',\r | |
352 | '{#}. {name}',\r | |
353 | '</tpl></p>'\r | |
354 | );\r | |
355 | var s = tpl.apply(data.kids);\r | |
356 | expect(s).toEqual('<p>Kids: 1. Joshua,2. Nina,3. Solomon</p>');\r | |
357 | });\r | |
358 | \r | |
359 | it('should handle "." and "parent" in loop', function () {\r | |
360 | var tpl = new Ext.XTemplate(\r | |
361 | '<div id="{id}-body" class="{baseCls}-body',\r | |
362 | '<tpl if="bodyCls"> {bodyCls}</tpl>',\r | |
363 | '<tpl if="uiCls">',\r | |
364 | '<tpl for="uiCls"> {parent.baseCls}-body-{parent.ui}-{.}</tpl>',\r | |
365 | '</tpl>"',\r | |
366 | '<tpl if="bodyStyle"> style="{bodyStyle}"</tpl>>',\r | |
367 | '</div>'\r | |
368 | );\r | |
369 | var s = tpl.apply({\r | |
370 | baseCls: 'x-panel-header',\r | |
371 | componentCls: 'x-panel-header',\r | |
372 | frame: false,\r | |
373 | id: 'header-1026',\r | |
374 | ui: 'default',\r | |
375 | uiCls: ['horizontal', 'top']\r | |
376 | });\r | |
377 | expect(s).toEqual('<div id="header-1026-body" class="x-panel-header-body x-panel-header-body-default-horizontal x-panel-header-body-default-top"></div>');\r | |
378 | });\r | |
379 | \r | |
380 | it('should handle <tpl for=""> like <tpl>', function() {\r | |
381 | tpl = new Ext.XTemplate(\r | |
382 | '<p>Kids: ',\r | |
383 | '<tpl for="">',\r | |
384 | '<p>{name}</p>',\r | |
385 | '</tpl></p>'\r | |
386 | );\r | |
387 | expect(tpl.apply(data.kids)).toEqual('<p>Kids: <p></p></p>');\r | |
388 | });\r | |
389 | \r | |
390 | it('should examine the data of parent object if for=".." is specified', function() {\r | |
391 | tpl = new Ext.XTemplate(\r | |
392 | '<p>Computer: ',\r | |
393 | '<tpl for="computers">',\r | |
394 | '<p>Cpu: {cpu} Hdd: {hdd}',\r | |
395 | '<tpl for="..">',\r | |
396 | ' User: {name}',\r | |
397 | '</tpl>',\r | |
398 | '</p>',\r | |
399 | '</tpl></p>'\r | |
400 | );\r | |
401 | var s = tpl.apply(data);\r | |
402 | expect(s).toEqual('<p>Computer: <p>Cpu: 2Ghz Hdd: 1To User: Nicolas Ferrero</p><p>Cpu: 100Mhz Hdd: 500Mo User: Nicolas Ferrero</p></p>');\r | |
403 | });\r | |
404 | \r | |
405 | it("should be able to access specified members of the provided data object (include array index test)", function() {\r | |
406 | tpl = new Ext.XTemplate(\r | |
407 | '<p>Name: {name}</p>',\r | |
408 | '<p>Title: {title}</p>',\r | |
409 | '<p>Company: {company}</p>',\r | |
410 | '<p>Kids: ',\r | |
411 | '<tpl for="kids">',\r | |
412 | '<p>{#}. {name}</p>',\r | |
413 | '</tpl></p>'\r | |
414 | );\r | |
415 | expect(tpl.apply(data)).toEqual('<p>Name: Nicolas Ferrero</p><p>Title: Developer</p><p>Company: Sencha</p><p>Kids: <p>1. Joshua</p><p>2. Nina</p><p>3. Solomon</p></p>');\r | |
416 | });\r | |
417 | \r | |
418 | describe("{.}", function(){\r | |
419 | it("should be able to auto-render flat array content with special variable {.} (include array index test)", function() {\r | |
420 | tpl = new Ext.XTemplate(\r | |
421 | '<p>{name}\'s favorite beverages:</p>',\r | |
422 | '<tpl for="drinks">',\r | |
423 | '<div>{#} - {.}</div>',\r | |
424 | '</tpl>'\r | |
425 | );\r | |
426 | expect(tpl.apply(data)).toEqual("<p>Nicolas Ferrero's favorite beverages:</p><div>1 - Wine</div><div>2 - Coffee</div><div>3 - Corona</div>");\r | |
427 | });\r | |
428 | \r | |
429 | it("should render numbers, strings, booleans, and dates, but not objects or arrays", function(){\r | |
430 | tpl = new Ext.XTemplate('<tpl for=".">{.}</tpl>');\r | |
431 | var date = new Date();\r | |
432 | expect(tpl.apply([1, true, 2.3, false, 'test', [1, 2, 3], {a:1, b:2}, 'ing', date, undefined, null])).toEqual('1true2.3falsetesting' + date);\r | |
433 | });\r | |
434 | });\r | |
435 | \r | |
436 | it("should not fail if for try to handle an undefined variable.", function() {\r | |
437 | tpl = new Ext.XTemplate(\r | |
438 | '<p>{name}\'s:</p>',\r | |
439 | '<tpl for="nothing">',\r | |
440 | '<div>{nothing1}</div>',\r | |
441 | '</tpl>{badness}<p>Foo</p>'\r | |
442 | );\r | |
443 | var s = tpl.apply(data);\r | |
444 | expect(s).toEqual("<p>Nicolas Ferrero's:</p><p>Foo</p>");\r | |
445 | });\r | |
446 | \r | |
447 | describe("parent", function() {\r | |
448 | \r | |
449 | it("should be able to access parent object member via the parent object", function() {\r | |
450 | tpl = new Ext.XTemplate(\r | |
451 | '<p>Name: {name}</p>',\r | |
452 | '<p>Kids: ',\r | |
453 | '<tpl for="kids">',\r | |
454 | '<tpl if="age > 1">',\r | |
455 | '<p>{name}</p>',\r | |
456 | '<p>Dad: {parent.name}</p>',\r | |
457 | '</tpl>',\r | |
458 | '</tpl></p>'\r | |
459 | );\r | |
460 | var s = tpl.apply(data);\r | |
461 | expect(s).toEqual("<p>Name: Nicolas Ferrero</p><p>Kids: <p>Joshua</p><p>Dad: Nicolas Ferrero</p><p>Nina</p><p>Dad: Nicolas Ferrero</p></p>");\r | |
462 | });\r | |
463 | \r | |
464 | it("should set the parent to the parent array if the action is '.'", function(){\r | |
465 | var tpl = new Ext.XTemplate(\r | |
466 | '<tpl for=".">',\r | |
467 | '{parent.specialProp}',\r | |
468 | '<tpl for=".">',\r | |
469 | '{parent.specialProp}{.}',\r | |
470 | '</tpl>',\r | |
471 | '</tpl>'\r | |
472 | );\r | |
473 | \r | |
474 | var data = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];\r | |
475 | data.specialProp = 'test';\r | |
476 | data[0].specialProp = 'foo';\r | |
477 | data[1].specialProp = 'bar';\r | |
478 | data[2].specialProp = 'baz';\r | |
479 | \r | |
480 | var s = tpl.apply(data);\r | |
481 | expect(s).toBe('testfoo1foo2foo3testbar4bar5bar6testbaz7baz8baz9');\r | |
482 | });\r | |
483 | \r | |
484 | it("should work with nested parents", function(){\r | |
485 | var tpl = new Ext.XTemplate(\r | |
486 | '{name}',\r | |
487 | '<tpl for="children">',\r | |
488 | '{name}{parent.name}',\r | |
489 | '<tpl for="children">',\r | |
490 | '{name}{parent.name}',\r | |
491 | '</tpl>',\r | |
492 | '</tpl>'\r | |
493 | );\r | |
494 | \r | |
495 | var s = tpl.apply({ \r | |
496 | name : 'A1', \r | |
497 | children : [{ \r | |
498 | name : 'B1', \r | |
499 | children : [{ \r | |
500 | name : 'C1' \r | |
501 | }, {\r | |
502 | name: 'C2'\r | |
503 | }] \r | |
504 | }, {\r | |
505 | name: 'B2',\r | |
506 | children : [{ \r | |
507 | name : 'C3' \r | |
508 | }, {\r | |
509 | name: 'C4'\r | |
510 | }]\r | |
511 | }] \r | |
512 | });\r | |
513 | expect(s).toBe('A1B1A1C1B1C2B1B2A1C3B2C4B2');\r | |
514 | });\r | |
515 | \r | |
516 | it("should reset the parent correctly during looping", function(){\r | |
517 | var data = [{\r | |
518 | id: 1,\r | |
519 | level2: [{\r | |
520 | id: 11,\r | |
521 | level3: [{\r | |
522 | id: 111\r | |
523 | }, {\r | |
524 | id: 112\r | |
525 | }, {\r | |
526 | id: 113\r | |
527 | }]\r | |
528 | }, {\r | |
529 | id: 12,\r | |
530 | level3: [{\r | |
531 | id: 121\r | |
532 | }, {\r | |
533 | id: 122\r | |
534 | }, {\r | |
535 | id: 123\r | |
536 | }]\r | |
537 | }, {\r | |
538 | id: 13,\r | |
539 | level3: [{\r | |
540 | id: 131\r | |
541 | }, {\r | |
542 | id: 132\r | |
543 | }, {\r | |
544 | id: 133\r | |
545 | }]\r | |
546 | }]\r | |
547 | }, {\r | |
548 | id: 2,\r | |
549 | level2: [{\r | |
550 | id: 21,\r | |
551 | level3: []\r | |
552 | }, {\r | |
553 | id: 22,\r | |
554 | level3: []\r | |
555 | }]\r | |
556 | }];\r | |
557 | \r | |
558 | var tpl = new Ext.XTemplate(\r | |
559 | '<tpl for=".">',\r | |
560 | 'level 1: id: {id}',\r | |
561 | '<tpl for="level2">',\r | |
562 | 'level 2: id: {id}, parent.id: {parent.id}',\r | |
563 | '<tpl for="level3">',\r | |
564 | 'level 3: id: {id}, parent.id: {parent.id}',\r | |
565 | '</tpl>',\r | |
566 | '</tpl>',\r | |
567 | '</tpl>'\r | |
568 | );\r | |
569 | \r | |
570 | expect(tpl.apply(data)).toBe([\r | |
571 | 'level 1: id: 1',\r | |
572 | 'level 2: id: 11, parent.id: 1',\r | |
573 | 'level 3: id: 111, parent.id: 11',\r | |
574 | 'level 3: id: 112, parent.id: 11',\r | |
575 | 'level 3: id: 113, parent.id: 11',\r | |
576 | 'level 2: id: 12, parent.id: 1',\r | |
577 | 'level 3: id: 121, parent.id: 12',\r | |
578 | 'level 3: id: 122, parent.id: 12',\r | |
579 | 'level 3: id: 123, parent.id: 12',\r | |
580 | 'level 2: id: 13, parent.id: 1',\r | |
581 | 'level 3: id: 131, parent.id: 13',\r | |
582 | 'level 3: id: 132, parent.id: 13',\r | |
583 | 'level 3: id: 133, parent.id: 13',\r | |
584 | 'level 1: id: 2',\r | |
585 | 'level 2: id: 21, parent.id: 2',\r | |
586 | 'level 2: id: 22, parent.id: 2'\r | |
587 | ].join(''));\r | |
588 | });\r | |
589 | });\r | |
590 | \r | |
591 | it("should be able to access child object like a tree", function() {\r | |
592 | tpl = new Ext.XTemplate("{something.child.name}");\r | |
593 | expect(tpl.apply(data)).toEqual("child");\r | |
594 | });\r | |
595 | \r | |
596 | it('should handle sequential for loops nested in for loop using arrays', function () {\r | |
597 | // this bug one was found by Brian's calendar templates\r | |
598 | tpl = new Ext.XTemplate(\r | |
599 | '<tpl for="arrays">',\r | |
600 | '<tpl for=".">',\r | |
601 | '_{name}_',\r | |
602 | '</tpl>',\r | |
603 | '<tpl for=".">',\r | |
604 | '-{name}-',\r | |
605 | '</tpl>',\r | |
606 | '/',\r | |
607 | '</tpl>'\r | |
608 | );\r | |
609 | \r | |
610 | var s = tpl.apply(arrayData);\r | |
611 | expect(s).toEqual('_Item A1__Item A2_-Item A1--Item A2-/'+\r | |
612 | '_Item B1__Item B2_-Item B1--Item B2-/');\r | |
613 | });\r | |
614 | \r | |
615 | it("should set the xindex variable correctly when looping over nested arrays", function() {\r | |
616 | var result = new Ext.XTemplate(\r | |
617 | '<tpl for=".">',\r | |
618 | '{% if (Ext.isArray(values)) { %}',\r | |
619 | '<tpl for=".">',\r | |
620 | '{#}',\r | |
621 | '</tpl>',\r | |
622 | '{% } %}',\r | |
623 | '{#}',\r | |
624 | '</tpl>'\r | |
625 | ).apply([1,1,1,[1,1],1]);\r | |
626 | expect(result).toBe('1231245');\r | |
627 | });\r | |
628 | }); // for\r | |
629 | \r | |
630 | describe("foreach", function () {\r | |
631 | \r | |
632 | it('should examine the data object provided if foreach="." is specified', function() {\r | |
633 | var tpl = new Ext.XTemplate(\r | |
634 | '<tpl foreach=".">',\r | |
635 | '{% if (Ext.isObject(values)) { %}',\r | |
636 | '<tpl foreach=".">',\r | |
637 | '{[xkey]} {[values]}.',\r | |
638 | '</tpl>',\r | |
639 | '{% } %}',\r | |
640 | '{$} {.}.',\r | |
641 | '</tpl>'\r | |
642 | ), \r | |
643 | result = Ext.Array.sort(tpl.apply(objectData).split('.'));\r | |
644 | \r | |
645 | expect(result[1]).toBe('a aValue');\r | |
646 | expect(result[2]).toBe('b ');\r | |
647 | expect(result[3]).toBe('c cValue');\r | |
648 | expect(result[4]).toBe('x xValue');\r | |
649 | expect(result[5]).toBe('y yValue');\r | |
650 | });\r | |
651 | \r | |
652 | it('should handle "." and "parent" in loop', function () {\r | |
653 | var tpl = new Ext.XTemplate(\r | |
654 | '<div id="{id}-body" class="{baseCls}-body',\r | |
655 | '<tpl if="bodyCls"> {bodyCls}</tpl>',\r | |
656 | '<tpl if="uiCls">',\r | |
657 | '<tpl foreach="uiCls"> {parent.baseCls}-body-{parent.ui}-{.}</tpl>',\r | |
658 | '</tpl>"',\r | |
659 | '<tpl if="bodyStyle"> style="{bodyStyle}"</tpl>>',\r | |
660 | '</div>'\r | |
661 | ),\r | |
662 | result = tpl.apply({\r | |
663 | baseCls: 'x-panel-header',\r | |
664 | componentCls: 'x-panel-header',\r | |
665 | frame: false,\r | |
666 | id: 'header-1026',\r | |
667 | ui: 'default',\r | |
668 | uiCls: {\r | |
669 | h: 'horizontal', \r | |
670 | t: 'top'\r | |
671 | }\r | |
672 | });\r | |
673 | expect(result).toEqual('<div id="header-1026-body" class="x-panel-header-body x-panel-header-body-default-horizontal x-panel-header-body-default-top"></div>');\r | |
674 | });\r | |
675 | \r | |
676 | it('should handle <tpl foreach=""> like <tpl>', function() {\r | |
677 | var tpl = new Ext.XTemplate(\r | |
678 | '<p>Kids: ',\r | |
679 | '<tpl foreach="">',\r | |
680 | '<p>{name}</p>',\r | |
681 | '</tpl></p>'\r | |
682 | );\r | |
683 | expect(tpl.apply(data.kids)).toEqual('<p>Kids: <p></p></p>');\r | |
684 | });\r | |
685 | \r | |
686 | it('should examine the data of parent object if for=".." is specified', function() {\r | |
687 | var tpl = new Ext.XTemplate(\r | |
688 | '<tpl foreach="b">',\r | |
689 | '<p>{$} {.}</p>',\r | |
690 | '<tpl for="..">',\r | |
691 | 'a: {a}',\r | |
692 | '</tpl>',\r | |
693 | '</p>',\r | |
694 | '</tpl></p>'\r | |
695 | );\r | |
696 | expect(tpl.apply(objectData)).toEqual('<p>x xValue</p>a: aValue</p><p>y yValue</p>a: aValue</p></p>');\r | |
697 | });\r | |
698 | \r | |
699 | it('should insert "between" values', function() {\r | |
700 | var tpl = new Ext.XTemplate(\r | |
701 | '<tpl foreach="b" between=",">',\r | |
702 | '{$}: {.}',\r | |
703 | '</tpl>'\r | |
704 | );\r | |
705 | expect(tpl.apply(objectData)).toEqual('x: xValue,y: yValue');\r | |
706 | });\r | |
707 | \r | |
708 | it("should be able to access the xindex using {#}", function() {\r | |
709 | var tpl = new Ext.XTemplate(\r | |
710 | '<tpl foreach="kids">',\r | |
711 | '{#}',\r | |
712 | '</tpl>'\r | |
713 | );\r | |
714 | expect(tpl.apply(data)).toEqual('123');\r | |
715 | });\r | |
716 | \r | |
717 | it("should not loop if foreach is passed an undefined variable.", function() {\r | |
718 | var tpl = new Ext.XTemplate(\r | |
719 | '<p>{name}\'s:</p>',\r | |
720 | '<tpl foreach="nothing">',\r | |
721 | '<div>{#}{$}{.}{nothing1}</div>',\r | |
722 | '</tpl>{badness}<p>Foo</p>'\r | |
723 | );\r | |
724 | expect(tpl.apply(data)).toEqual("<p>Nicolas Ferrero's:</p><p>Foo</p>");\r | |
725 | });\r | |
726 | \r | |
727 | describe("parent", function() {\r | |
728 | \r | |
729 | it("should be able to access parent object member via the parent object", function() {\r | |
730 | var tpl = new Ext.XTemplate(\r | |
731 | '<tpl foreach="b">',\r | |
732 | '<p>{parent.c}</p>',\r | |
733 | '</tpl>'\r | |
734 | );\r | |
735 | expect(tpl.apply(objectData)).toEqual("<p>cValue</p><p>cValue</p>");\r | |
736 | });\r | |
737 | \r | |
738 | it("should set the parent to the parent object if the action is '.'", function(){\r | |
739 | var tpl = new Ext.XTemplate(\r | |
740 | '<tpl foreach=".">',\r | |
741 | '{parent.x}',\r | |
742 | '</tpl>'\r | |
743 | ), data = {\r | |
744 | x: 1,\r | |
745 | y: 2,\r | |
746 | z: 3\r | |
747 | };\r | |
748 | \r | |
749 | expect(tpl.apply(data)).toBe('111'); \r | |
750 | });\r | |
751 | });\r | |
752 | \r | |
753 | it("should set the xindex variable correctly when looping over nested objects", function() {\r | |
754 | var result = new Ext.XTemplate(\r | |
755 | '<tpl foreach=".">',\r | |
756 | '{% if (Ext.isObject(values)) { %}',\r | |
757 | '<tpl foreach=".">',\r | |
758 | '{#}',\r | |
759 | '</tpl>',\r | |
760 | '{% } %}',\r | |
761 | '{#}',\r | |
762 | '</tpl>'\r | |
763 | ).apply({a:1,b:1,c:1,d:{e:1,f:1},g:1});\r | |
764 | expect(result).toBe('1231245');\r | |
765 | });\r | |
766 | }); // foreach\r | |
767 | \r | |
768 | describe("insane overnesting of for and foreach loops", function () {\r | |
769 | it("should apply the template", function() {\r | |
770 | var id = 0,\r | |
771 | data = (function assignIds(data) {\r | |
772 | if (data instanceof Object) {\r | |
773 | data.id = id++;\r | |
774 | if (data instanceof Array) {\r | |
775 | Ext.Array.each(data, function(item) {\r | |
776 | assignIds(item);\r | |
777 | });\r | |
778 | } else {\r | |
779 | Ext.Object.each(data, function(key, value) {\r | |
780 | assignIds(value);\r | |
781 | });\r | |
782 | }\r | |
783 | }\r | |
784 | return data;\r | |
785 | })({\r | |
786 | a: [{\r | |
787 | b: [1, 2],\r | |
788 | c: {d: 3, e: 4}\r | |
789 | }, {\r | |
790 | f: {g: 5, h: 6},\r | |
791 | i: [7, 8]\r | |
792 | }, [\r | |
793 | {j: 9, k: 10},\r | |
794 | [11, 12]\r | |
795 | ]],\r | |
796 | l: {\r | |
797 | m: [{n: 13, o: 14}],\r | |
798 | p: [[15, 16], [17, 18]]\r | |
799 | }\r | |
800 | }),\r | |
801 | tpl = new Ext.XTemplate(\r | |
802 | '<tpl foreach=".">',\r | |
803 | '[key]{$}',\r | |
804 | '{% if (Ext.isObject(values)) { %}',\r | |
805 | '<tpl foreach=".">',\r | |
806 | '[key]{$}',\r | |
807 | '{% if (Ext.isObject(values)) { %}',\r | |
808 | '<tpl foreach=".">',\r | |
809 | '[key]{$}',\r | |
810 | '{% if (Ext.isObject(values)) { %}',\r | |
811 | '<tpl foreach=".">',\r | |
812 | '[key]{$}[value]{.}[parent]{parent.id}[index]{#}',\r | |
813 | '</tpl>',\r | |
814 | '{% } %}',\r | |
815 | '{% else if (Ext.isArray(values)) { %}',\r | |
816 | '<tpl for=".">',\r | |
817 | '[value]{.}[parent]{parent.id}[index]{#}',\r | |
818 | '</tpl>',\r | |
819 | '{% } %}',\r | |
820 | '[parent]{parent.id}[index]{#}',\r | |
821 | '</tpl>',\r | |
822 | '{% } %}',\r | |
823 | '{% else if (Ext.isArray(values)) { %}',\r | |
824 | '<tpl for=".">',\r | |
825 | '{% if (Ext.isObject(values)) { %}',\r | |
826 | '<tpl foreach=".">',\r | |
827 | '[key]{$}[value]{.}[parent]{parent.id}[index]{#}',\r | |
828 | '</tpl>',\r | |
829 | '{% } %}',\r | |
830 | '{% else if (Ext.isArray(values)) { %}',\r | |
831 | '<tpl for=".">',\r | |
832 | '[value]{.}[parent]{parent.id}[index]{#}',\r | |
833 | '</tpl>',\r | |
834 | '{% } %}',\r | |
835 | '[parent]{parent.id}[index]{#}',\r | |
836 | '</tpl>',\r | |
837 | '{% } %}',\r | |
838 | '[parent]{parent.id}[index]{#}',\r | |
839 | '</tpl>',\r | |
840 | '{% } %}',\r | |
841 | '{% else if (Ext.isArray(values)) { %}',\r | |
842 | '<tpl for=".">',\r | |
843 | '{% if (Ext.isObject(values)) { %}',\r | |
844 | '<tpl foreach=".">',\r | |
845 | '[key]{$}',\r | |
846 | '{% if (Ext.isObject(values)) { %}',\r | |
847 | '<tpl foreach=".">',\r | |
848 | '[key]{$}[value]{.}[parent]{parent.id}[index]{#}',\r | |
849 | '</tpl>',\r | |
850 | '{% } %}',\r | |
851 | '{% else if (Ext.isArray(values)) { %}',\r | |
852 | '<tpl for=".">',\r | |
853 | '[value]{.}[parent]{parent.id}[index]{#}',\r | |
854 | '</tpl>',\r | |
855 | '{% } %}',\r | |
856 | '[parent]{parent.id}[index]{#}',\r | |
857 | '</tpl>',\r | |
858 | '{% } %}',\r | |
859 | '{% else if (Ext.isArray(values)) { %}',\r | |
860 | '<tpl for=".">',\r | |
861 | '{% if (Ext.isObject(values)) { %}',\r | |
862 | '<tpl foreach=".">',\r | |
863 | '[key]{$}[value]{.}[parent]{parent.id}[index]{#}',\r | |
864 | '</tpl>',\r | |
865 | '{% } %}',\r | |
866 | '{% else if (Ext.isArray(values)) { %}',\r | |
867 | '<tpl for=".">',\r | |
868 | '[value]{.}[parent]{parent.id}[index]{#}',\r | |
869 | '</tpl>',\r | |
870 | '{% } %}',\r | |
871 | '[parent]{parent.id}[index]{#}',\r | |
872 | '</tpl>',\r | |
873 | '{% } %}',\r | |
874 | '[parent]{parent.id}[index]{#}',\r | |
875 | '</tpl>',\r | |
876 | '{% } %}',\r | |
877 | '[parent]{parent.id}[index]{#}',\r | |
878 | '</tpl>'\r | |
879 | );\r | |
880 | \r | |
881 | // Although not required by the ecmascript spec, all modern browsers currently\r | |
882 | // loop object properties in the order they/ were defined, which is why the\r | |
883 | // following expectation passes. If this ever changes in the future, we may\r | |
884 | // have to revisit this spec.\r | |
885 | expect(tpl.apply(data)).toBe([\r | |
886 | '[key]a[key]b[value]1[parent]3[index]1[value]2[parent]3[index]2',\r | |
887 | '[parent]2[index]1[key]c[key]d[value]3[parent]4[index]1[key]e[value]4',\r | |
888 | '[parent]4[index]2[key]id[value]4[parent]4[index]3[parent]2[index]2',\r | |
889 | '[key]id[parent]2[index]3[parent]1[index]1[key]f[key]g[value]5[parent]6',\r | |
890 | '[index]1[key]h[value]6[parent]6[index]2[key]id[value]6[parent]6[index]3',\r | |
891 | '[parent]5[index]1[key]i[value]7[parent]7[index]1[value]8[parent]7',\r | |
892 | '[index]2[parent]5[index]2[key]id[parent]5[index]3[parent]1[index]2',\r | |
893 | '[key]j[value]9[parent]9[index]1[key]k[value]10[parent]9[index]2',\r | |
894 | '[key]id[value]9[parent]9[index]3[parent]8[index]1[value]11[parent]10',\r | |
895 | '[index]1[value]12[parent]10[index]2[parent]8[index]2[parent]1[index]3',\r | |
896 | '[parent]0[index]1[key]l[key]m[key]n[value]13[parent]13[index]1[key]o',\r | |
897 | '[value]14[parent]13[index]2[key]id[value]13[parent]13[index]3[parent]12',\r | |
898 | '[index]1[parent]11[index]1[key]p[value]15[parent]15[index]1[value]16',\r | |
899 | '[parent]15[index]2[parent]14[index]1[value]17[parent]16[index]1',\r | |
900 | '[value]18[parent]16[index]2[parent]14[index]2[parent]11[index]2[key]id',\r | |
901 | '[parent]11[index]3[parent]0[index]2[key]id[parent]0[index]3'\r | |
902 | ].join(''));\r | |
903 | });\r | |
904 | });\r | |
905 | \r | |
906 | describe("exec", function() {\r | |
907 | it("should considerer that anything between {[ ... ]} is code to be executed in the scope of the template", function() {\r | |
908 | tpl = new Ext.XTemplate(\r | |
909 | '<p>Name: {name}</p>',\r | |
910 | '<p>Company: {[values.company.toUpperCase() + ", " + values.title]}</p>',\r | |
911 | '<p>Kids: ',\r | |
912 | '<tpl for="kids">',\r | |
913 | '<div class="{[xindex % 2 === 0 ? "even" : "odd"]}">',\r | |
914 | '{[fm.ellipsis(values.name, 5)]}/{[xcount]}',\r | |
915 | '</div>',\r | |
916 | '</tpl></p>'\r | |
917 | );\r | |
918 | var s = tpl.apply(data);\r | |
919 | expect(s).toEqual('<p>Name: Nicolas Ferrero</p><p>Company: SENCHA, Developer</p><p>Kids: <div class="odd">Jo.../3</div><div class="even">Nina/3</div><div class="odd">So.../3</div></p>');\r | |
920 | });\r | |
921 | });\r | |
922 | \r | |
923 | it('should handle <tpl exec=""> like <tpl>', function() {\r | |
924 | tpl = new Ext.XTemplate(\r | |
925 | '<p>Kids: ',\r | |
926 | '<tpl exec="++this.foo">',\r | |
927 | '<p>{name}</p>',\r | |
928 | '</tpl></p>',\r | |
929 | {\r | |
930 | foo: 1\r | |
931 | }\r | |
932 | );\r | |
933 | var s = tpl.apply(data.kids);\r | |
934 | expect(tpl.foo).toEqual(2);\r | |
935 | expect(s).toEqual('<p>Kids: <p></p></p>');\r | |
936 | });\r | |
937 | \r | |
938 | it('should handle nested tags', function() {\r | |
939 | tpl = new Ext.XTemplate(\r | |
940 | '{{id}-bar}'\r | |
941 | );\r | |
942 | var s = tpl.apply({\r | |
943 | id: 'foo'\r | |
944 | });\r | |
945 | \r | |
946 | expect(s).toEqual('{foo-bar}');\r | |
947 | });\r | |
948 | \r | |
949 | describe("execute code without producing any output with exec operator", function() {\r | |
950 | describe("simple exec operator", function() {\r | |
951 | beforeEach(function() {\r | |
952 | tpl = new Ext.XTemplate(\r | |
953 | '<tpl for="kids">',\r | |
954 | '<tpl exec="++this.calls; return 1">',\r | |
955 | '<p>{name}</p>',\r | |
956 | '</tpl>',\r | |
957 | '</tpl>',\r | |
958 | {\r | |
959 | calls: 0\r | |
960 | });\r | |
961 | });\r | |
962 | \r | |
963 | it("should execute the code", function() {\r | |
964 | tpl.apply(data);\r | |
965 | expect(tpl.calls).toEqual(3);\r | |
966 | });\r | |
967 | \r | |
968 | it("should not interfere with output even if exec return a value", function() {\r | |
969 | expect(tpl.apply(data)).toEqual('<p>Joshua</p><p>Nina</p><p>Solomon</p>');\r | |
970 | });\r | |
971 | });\r | |
972 | \r | |
973 | describe("for and exec declared in the same tpl tag", function() {\r | |
974 | beforeEach(function() {\r | |
975 | tpl = new Ext.XTemplate(\r | |
976 | '<tpl for="kids" exec="this.spy(values, xindex, parent); return 1">',\r | |
977 | '<p>{[this.spy.calls.length]}. {name}</p>',\r | |
978 | '</tpl>',\r | |
979 | {\r | |
980 | spy : jasmine.createSpy("tplMemberSpy")\r | |
981 | });\r | |
982 | \r | |
983 | });\r | |
984 | \r | |
985 | it("should execute code for each item in the array", function() {\r | |
986 | tpl.apply(data);\r | |
987 | expect(tpl.spy.calls.length).toEqual(3);\r | |
988 | });\r | |
989 | \r | |
990 | \r | |
991 | it("should be run for each item in the array with index of the loop you are in, values of the current scope, and scope of ancestor template", function() {\r | |
992 | tpl.apply(data);\r | |
993 | expect(tpl.spy.calls[0].args).toEqual([data.kids[0], 1, data]);\r | |
994 | expect(tpl.spy.calls[1].args).toEqual([data.kids[1], 2, data]);\r | |
995 | expect(tpl.spy.calls[2].args).toEqual([data.kids[2], 3, data]);\r | |
996 | });\r | |
997 | \r | |
998 | it("should not interfere with output even if exec return a value", function() {\r | |
999 | expect(tpl.apply(data)).toEqual('<p>0. Joshua</p><p>1. Nina</p><p>2. Solomon</p>');\r | |
1000 | });\r | |
1001 | });\r | |
1002 | \r | |
1003 | describe("if and exec declared in the same tpl tag", function() {\r | |
1004 | beforeEach(function() {\r | |
1005 | tpl = new Ext.XTemplate(\r | |
1006 | '<tpl for="kids">',\r | |
1007 | '<tpl if="name == \'Joshua\'" exec="this.inc++; return 1">',\r | |
1008 | '<p>{[this.inc]} - {name}</p>',\r | |
1009 | '</tpl>',\r | |
1010 | '</tpl>',\r | |
1011 | {\r | |
1012 | inc : 0\r | |
1013 | });\r | |
1014 | \r | |
1015 | });\r | |
1016 | \r | |
1017 | it("should be run only if the if operator conditional checks is true", function() {\r | |
1018 | tpl.apply(data);\r | |
1019 | expect(tpl.inc).toEqual(1);\r | |
1020 | });\r | |
1021 | \r | |
1022 | it("should not interfere with output", function() {\r | |
1023 | expect(tpl.apply(data)).toEqual('<p>1 - Joshua</p>');\r | |
1024 | });\r | |
1025 | });\r | |
1026 | });\r | |
1027 | });\r | |
1028 | \r | |
1029 | describe("template member functions", function() {\r | |
1030 | var spy;\r | |
1031 | beforeEach(function() {\r | |
1032 | spy = jasmine.createSpy("membersArguments").andCallFake(function(value, suffix, limit) {\r | |
1033 | return Ext.String.ellipsis(value + ' ' + suffix, 13);\r | |
1034 | });\r | |
1035 | tpl = new Ext.XTemplate(\r | |
1036 | '<p>{[this.addMr(values.name)]}</p>',\r | |
1037 | '<p>Company: {company:this.spy("Incorporated", 10)}</p>',\r | |
1038 | '<p>Title: {title:this.addJs()}</p>',\r | |
1039 | '<p>Kids: ',\r | |
1040 | '<tpl for="kids">',\r | |
1041 | '<tpl if="this.isGirl(name)">',\r | |
1042 | '<p>Girl: {name} - {age}</p>',\r | |
1043 | '<tpl else>',\r | |
1044 | '<p>Boy: {name} - {age}</p>',\r | |
1045 | '</tpl>',\r | |
1046 | '<tpl if="this.isBaby(age)">',\r | |
1047 | '<p>{name} is a baby!</p>',\r | |
1048 | '</tpl>',\r | |
1049 | '</tpl></p>',\r | |
1050 | {\r | |
1051 | addMr: function(name) {\r | |
1052 | return "Mr. " + name;\r | |
1053 | },\r | |
1054 | addJs: function(title) {\r | |
1055 | return "Js " + title;\r | |
1056 | },\r | |
1057 | isGirl: function(name) {\r | |
1058 | return name == 'Nina';\r | |
1059 | },\r | |
1060 | isBaby: function(age) {\r | |
1061 | return age < 1;\r | |
1062 | },\r | |
1063 | spy: spy\r | |
1064 | }\r | |
1065 | );\r | |
1066 | });\r | |
1067 | \r | |
1068 | it("should call members functions using various methods", function() {\r | |
1069 | var s = tpl.apply(data);\r | |
1070 | expect(s).toEqual("<p>Mr. Nicolas Ferrero</p><p>Company: Sencha Inc...</p><p>Title: Js Developer</p><p>Kids: <p>Boy: Joshua - 3</p><p>Girl: Nina - 2</p><p>Boy: Solomon - 0</p><p>Solomon is a baby!</p></p>");\r | |
1071 | });\r | |
1072 | \r | |
1073 | it("should call members format functions with passed arguments", function() {\r | |
1074 | tpl.apply(data);\r | |
1075 | expect(spy).toHaveBeenCalledWith(data.company, "Incorporated", 10);\r | |
1076 | });\r | |
1077 | });\r | |
1078 | \r | |
1079 | describe("basic math support", function() {\r | |
1080 | it("should be able to apply basic math operators + - * / on numeric data values", function() {\r | |
1081 | tpl = new Ext.XTemplate(\r | |
1082 | '<tpl for="kids">',\r | |
1083 | '<p>{age + 5} {age - 7} {age * 3} {age / 2}</p>',\r | |
1084 | '<p>{age + (5*2)}</p>',\r | |
1085 | '</tpl>'\r | |
1086 | );\r | |
1087 | expect(tpl.apply(data)).toEqual("<p>8 -4 9 1.5</p><p>13</p><p>7 -5 6 1</p><p>12</p><p>5 -7 0 0</p><p>10</p>");\r | |
1088 | });\r | |
1089 | });\r | |
1090 | \r | |
1091 | describe("special characters", function(){\r | |
1092 | it("should handle newlines", function(){\r | |
1093 | tpl = new Ext.XTemplate('<div>\n</div>');\r | |
1094 | expect(tpl.apply()).toBe('<div>\n</div>');\r | |
1095 | });\r | |
1096 | \r | |
1097 | it("should handle empty braces", function(){\r | |
1098 | var s = 'cfg = cfg || {};';\r | |
1099 | tpl = new Ext.XTemplate(s);\r | |
1100 | expect(tpl.apply()).toBe(s); \r | |
1101 | });\r | |
1102 | \r | |
1103 | it("should handle curly braces literally if there is no tag match", function() {\r | |
1104 | expect(new Ext.XTemplate(\r | |
1105 | '{ foo} foobar {bar } barfoo { foo bar } { foo {bar}}{\nfoo}{foo\n} {foo\nbar}{{bar}}',\r | |
1106 | ''\r | |
1107 | ).apply({\r | |
1108 | bar: 'baz'\r | |
1109 | })).toBe('{ foo} foobar {bar } barfoo { foo bar } { foo baz}{\nfoo}{foo\n} {foo\nbar}{baz}');\r | |
1110 | });\r | |
1111 | });\r | |
1112 | \r | |
1113 | describe("Undefined and non-string properties", function(){\r | |
1114 | it("should ignore undefined", function () {\r | |
1115 | tpl = new Ext.XTemplate('-{foo}-');\r | |
1116 | expect(tpl.apply({})).toBe('--');\r | |
1117 | });\r | |
1118 | it("should ignore null", function () {\r | |
1119 | tpl = new Ext.XTemplate('-{foo}-');\r | |
1120 | expect(tpl.apply({foo:null})).toBe('--');\r | |
1121 | });\r | |
1122 | it("should ignore an empty string", function(){\r | |
1123 | tpl = new Ext.XTemplate('-{foo}-');\r | |
1124 | expect(tpl.apply({foo:''})).toBe('--');\r | |
1125 | });\r | |
1126 | it("should stringify false", function(){\r | |
1127 | tpl = new Ext.XTemplate('-{foo}-');\r | |
1128 | expect(tpl.apply({foo:false})).toBe('-false-');\r | |
1129 | });\r | |
1130 | it("should stringify zero", function(){\r | |
1131 | tpl = new Ext.XTemplate('-{foo}-');\r | |
1132 | expect(tpl.apply({foo:0})).toBe('-0-');\r | |
1133 | });\r | |
1134 | it("should evaluate undefined as false", function(){\r | |
1135 | tpl = new Ext.XTemplate('<tpl if="foo">foo<tpl else>not foo</tpl>');\r | |
1136 | expect(tpl.apply({})).toBe('not foo');\r | |
1137 | });\r | |
1138 | it("should evaluate null as false", function(){\r | |
1139 | tpl = new Ext.XTemplate('<tpl if="foo">foo<tpl else>not foo</tpl>');\r | |
1140 | expect(tpl.apply({foo:null})).toBe('not foo');\r | |
1141 | });\r | |
1142 | it("should evaluate zero as false", function(){\r | |
1143 | tpl = new Ext.XTemplate('<tpl if="foo">foo<tpl else>not foo</tpl>');\r | |
1144 | expect(tpl.apply({foo:0})).toBe('not foo');\r | |
1145 | });\r | |
1146 | });\r | |
1147 | \r | |
1148 | describe("formats", function() {\r | |
1149 | var appliedObject;\r | |
1150 | \r | |
1151 | beforeEach(function() {\r | |
1152 | appliedObject = {a: "123", b: "456789"};\r | |
1153 | });\r | |
1154 | \r | |
1155 | describe("enabled", function() {\r | |
1156 | beforeEach(function() {\r | |
1157 | tpl = new Ext.XTemplate(\r | |
1158 | '{a:ellipsis(2)}'\r | |
1159 | );\r | |
1160 | });\r | |
1161 | \r | |
1162 | it("should call ellipsis", function() {\r | |
1163 | expect(tpl.apply(appliedObject)).toEqual('...');\r | |
1164 | });\r | |
1165 | \r | |
1166 | });\r | |
1167 | \r | |
1168 | describe("disabled", function() {\r | |
1169 | beforeEach(function() {\r | |
1170 | tpl = new Ext.XTemplate(\r | |
1171 | '{a:ellipsis(2)}',\r | |
1172 | {disableFormats: true}\r | |
1173 | );\r | |
1174 | });\r | |
1175 | \r | |
1176 | it("should not call Ext.String.ellipsis", function() {\r | |
1177 | expect(tpl.apply(appliedObject)).toEqual('123');\r | |
1178 | });\r | |
1179 | });\r | |
1180 | \r | |
1181 | describe('method', function () {\r | |
1182 | it('should call a basic method', function () {\r | |
1183 | tpl = new Ext.XTemplate(\r | |
1184 | 'Linkify: {text:this.linkify}',\r | |
1185 | {\r | |
1186 | /**\r | |
1187 | * Simply wraps a link tag around each detected url\r | |
1188 | */\r | |
1189 | linkify: function(value) {\r | |
1190 | return value.replace(/(http:\/\/[^\s]*)/g, "<a target=\"_blank\" href=\"$1\">$1</a>");\r | |
1191 | }\r | |
1192 | }\r | |
1193 | );\r | |
1194 | var s = tpl.apply({ text: 'This page http://foo.bar.com/foobar.html is cool' });\r | |
1195 | expect(s).toEqual('Linkify: This page <a target="_blank" href="http://foo.bar.com/foobar.html">http://foo.bar.com/foobar.html</a> is cool');\r | |
1196 | });\r | |
1197 | });\r | |
1198 | });\r | |
1199 | \r | |
1200 | describe("Ext.XTemplate.from", function() {\r | |
1201 | var elWithHtml, elWithValue;\r | |
1202 | \r | |
1203 | beforeEach(function() {\r | |
1204 | elWithHtml = Ext.getBody().createChild({tag: "div", html:"FOO {0}."});\r | |
1205 | elWithValue = Ext.getBody().createChild({tag: "input"});\r | |
1206 | elWithValue.dom.value = "BAR {0}.";\r | |
1207 | });\r | |
1208 | \r | |
1209 | afterEach(function() {\r | |
1210 | elWithHtml.remove();\r | |
1211 | elWithValue.remove();\r | |
1212 | });\r | |
1213 | \r | |
1214 | it("should create a template with dom element innerHTML", function() {\r | |
1215 | tpl = Ext.XTemplate.from(elWithHtml);\r | |
1216 | \r | |
1217 | expect(tpl.apply(['BAR'])).toEqual('FOO BAR.');\r | |
1218 | });\r | |
1219 | \r | |
1220 | it("should create a template with dom element value", function() {\r | |
1221 | tpl = Ext.XTemplate.from(elWithValue);\r | |
1222 | \r | |
1223 | expect(tpl.apply(['FOO'])).toEqual('BAR FOO.');\r | |
1224 | });\r | |
1225 | });\r | |
1226 | \r | |
1227 | describe('strict mode', function () {\r | |
1228 | it('should throw when substitution token is invalid', function () {\r | |
1229 | var tpl = new Ext.XTemplate('{foo.bar.baz}', {\r | |
1230 | strict: true\r | |
1231 | });\r | |
1232 | \r | |
1233 | expect(function () {\r | |
1234 | tpl.apply({});\r | |
1235 | }).toThrow();\r | |
1236 | });\r | |
1237 | \r | |
1238 | it('should throw when for expression is invalid', function () {\r | |
1239 | var tpl = new Ext.XTemplate('<tpl for="foo.bar.baz">{.}</tpl>', {\r | |
1240 | strict: true\r | |
1241 | });\r | |
1242 | \r | |
1243 | expect(function () {\r | |
1244 | tpl.apply({});\r | |
1245 | }).toThrow();\r | |
1246 | });\r | |
1247 | \r | |
1248 | it('should throw when if expression is invalid', function () {\r | |
1249 | var tpl = new Ext.XTemplate('<tpl if="foo.bar.baz">{.}</tpl>', {\r | |
1250 | strict: true\r | |
1251 | });\r | |
1252 | \r | |
1253 | expect(function () {\r | |
1254 | tpl.apply({});\r | |
1255 | }).toThrow();\r | |
1256 | });\r | |
1257 | });\r | |
1258 | });\r |