UNPKG

26.4 kBJavaScriptView Raw
1'use strict';
2var Velocity = require('../src/velocity')
3var assert = require("assert")
4var parse = Velocity.parse
5var Compile = Velocity.Compile
6
7describe('Compile', function() {
8
9 var render = Velocity.render;
10
11 function getContext(str, context, macros) {
12 var compile = new Compile(parse(str))
13 compile.render(context, macros)
14 return compile.context
15 }
16
17 describe('References', function() {
18
19 it('get/is method', function() {
20 var vm = '$customer.getAddress() $customer.getaddress()'
21 var vm1 = '$customer.get("address") $customer.get("Address")'
22 var vm3 = '$customer.isAddress() $customer.isaddress()'
23
24 assert.equal('bar bar', render(vm3, {customer: {Address: "bar"}}))
25
26 assert.equal('bar bar', render(vm, {customer: {address: "bar"}}))
27 assert.equal('foo bar', render(vm, {
28 customer: {
29 address: 'bar',
30 Address: 'foo'
31 }
32 }))
33
34 assert.equal('bar bar', render(vm1, {customer: {address: "bar"}}))
35 assert.equal('foo bar', render(vm1, {
36 customer: {
37 Address: 'bar',
38 address: 'foo'
39 }
40 }))
41 })
42
43 it('method with attribute', function() {
44 var vm = '$foo().bar\n${foo().bar}'
45 assert.equal('hello\nhello', render(vm, {
46 foo: function() {
47 return { bar: 'hello' }
48 }
49 }))
50
51 assert.equal('foo', render('${foo()}', {
52 foo: function() {
53 return 'foo'
54 }
55 }))
56 })
57
58 it('index notation', function() {
59 var vm = '$foo[0] $foo[$i] $foo.get(1) $xx["oo"]'
60 assert.equal('bar haha haha oo', render(vm, {foo: ["bar", "haha"], i: 1, xx: { oo: 'oo' }}))
61 })
62
63 it('set method', function() {
64 var vm = '$page.setTitle("My Home Page").setname("haha")' +
65 '$page.Title $page.name'
66 assert.equal('My Home Page haha', render(vm, {page: {}}))
67 })
68
69 it('runt type support', function() {
70 var vm = '$page.header(page)'
71 assert.equal('$page.header(page)', render(vm, {page: {}}))
72 })
73
74 it('size method', function() {
75 var vm = '$foo.bar.size()'
76 assert.equal('2', render(vm, {foo: {bar: [1, 2]}}))
77 assert.equal('2', render(vm, {foo: {bar: {a: 1, b: 3}}}))
78
79 var vm2 = '#if($foo.bar.size()) ok #{else} nosize #end'
80 assert.equal(' nosize ', render(vm2, {foo: {bar: 123}}))
81 assert.equal(' nosize ', render(vm2, {foo: {}}))
82
83 var vm3 = '$foo.size()';
84 function fooSize() {
85 return 3;
86 }
87 assert.equal('3', render(vm3, { foo: { size: fooSize } }))
88 })
89
90 it('quiet reference', function() {
91 var vm = 'my email is $email'
92 var vmquiet = 'my email is $!email.xxx'
93 assert.equal(vm, render(vm))
94 assert.equal('my email is ', render(vmquiet))
95 })
96
97 it('silence all reference', function() {
98 var vm = 'my email is $email'
99
100 var compile = new Compile(parse(vm))
101 assert.equal('my email is ', compile.render(null, null, true))
102 })
103
104 it('this context keep correct, see #16', function() {
105 var data = 'a = $a.get()'
106 function B(c) {
107 this.c = c
108 }
109
110 B.prototype.get = function() {
111 var t = this.eval(" hello $name", {name: 'hanwen'})
112 return this.c + t
113 }
114
115 assert.equal('a = 1 hello hanwen', render(data, {a: new B(1)}))
116 })
117
118 it('this context should keep corrent in macro', function() {
119 var data = '#parse()'
120 var Macro = function(name) {
121 this.name = name;
122 };
123
124 Macro.prototype.parse = function() {
125 return this.name;
126 };
127
128 assert.equal('hanwen', render(data, {}, new Macro('hanwen')))
129 })
130
131 it('get variable form text', function() {
132 var vm = 'hello $user.getName().getFullName("hanwen")'
133 var data = { '$user.getName().getFullName("hanwen")': 'world' }
134 assert.equal('hello world', render(vm, data))
135 })
136
137 it('escape false default', function() {
138 var vm = '$name $name2 $cn $cn1'
139 var data = {
140 name: 'hello world',
141 name2: '<i>&a',
142 cn: '中文',
143 cn1: '<i>中文'
144 }
145
146 var ret = 'hello world <i>&a 中文 <i>中文'
147 assert.equal(ret, render(vm, data))
148 })
149
150 it('escape true', function() {
151 var vm = '$name $name2 $cn $cn1'
152 var data = {
153 name: 'hello world',
154 name2: '<i>&a',
155 cn: '中文',
156 cn1: '<i>中文'
157 }
158
159 var ret = 'hello world &lt;i&gt;&amp;a 中文 &lt;i&gt;&#20013;&#25991;'
160 assert.equal(ret, render(vm, data, undefined, { escape: true }))
161 })
162
163 it('add custom ignore escape function', function() {
164 var vm = '$noIgnore($name), $ignore($name)'
165 var expected = '&lt;i&gt;, <i>'
166
167 var compile = new Compile(parse(vm), {
168 escape: true,
169 unescape: { ignore: true },
170 });
171
172 var context = {
173 name: '<i>',
174 noIgnore: function(name) {
175 return name
176 },
177
178 ignore: function(name) {
179 return name;
180 }
181 }
182
183 var ret = compile.render(context)
184 assert.equal(expected, ret)
185 })
186
187 it('config support', function() {
188 var vm = '$foo($name)'
189 var expected = '<i>'
190
191 var compile = new Compile(parse(vm), { escape: false })
192 var context = {
193 name: '<i>',
194 foo: function(name) {
195 return name;
196 }
197 }
198
199 var ret = compile.render(context)
200 assert.equal(expected, ret)
201
202 compile = new Compile(parse(vm), { escape: true, unescape: { foo: true } })
203 ret = compile.render(context)
204 assert.equal(expected, ret)
205
206 compile = new Compile(parse(vm), { escape: true })
207 ret = compile.render(context)
208 assert.equal('&lt;i&gt;', ret)
209 })
210
211 it ('valueMapper support', () => {
212 const values = [];
213 const vm = '#set($foo = "bar")\n$foo'
214 const ret = render(vm, {}, {}, {
215 valueMapper: (value) => {
216 values.push(value);
217 return 'foo';
218 },
219 });
220 assert.deepEqual(values, ['bar']);
221 assert.equal(ret.trim(), 'foo');
222 });
223
224 describe('env', function() {
225 it('should throw on property when parent is null', function() {
226 var vm = '$foo.bar';
227 var compile = new Compile(parse(vm), { env: 'development' })
228 function foo() {
229 compile.render()
230 };
231 foo.should.throw(/get property bar of undefined/);
232 });
233
234 it('should throw on index when parent is null', function() {
235 var vm = '$foo[1]';
236 var compile = new Compile(parse(vm), { env: 'development' })
237 function foo() {
238 compile.render()
239 };
240 foo.should.throw(/get property 1 of undefined/);
241 });
242
243 it('should throw on function when parent is null', function() {
244 var vm = '$foo.xx()';
245 var compile = new Compile(parse(vm), { env: 'development' })
246 function foo() {
247 compile.render()
248 };
249 foo.should.throw(/get property xx of undefined/);
250 });
251
252 it('should throw when mult level', function() {
253 var vm = '$foo.bar.xx.bar1';
254 var compile = new Compile(parse(vm), { env: 'development' })
255 function foo() {
256 compile.render({ foo: { bar: {} }});
257 };
258 foo.should.throw(/get property bar1 of undefined/);
259 });
260
261 it('not function', function() {
262 var vm = '$foo.bar.xx()';
263 var compile = new Compile(parse(vm), { env: 'development' })
264 function foo() {
265 return compile.render({ foo: { bar: {} }});
266 };
267 foo.should.throw(/xx is not method/);
268 });
269 });
270 })
271
272
273 describe('Literals', function() {
274
275 it("eval string value", function() {
276 var vm = '#set( $directoryRoot = "www" )' +
277 '#set( $templateName = "index.vm")' +
278 '#set( $template = "$directoryRoot/$templateName" )' +
279 '$template'
280
281 assert.equal('www/index.vm', render(vm))
282 })
283
284 it('not eval string', function() {
285 var vm = "#set( $blargh = '$foo' )$blargh"
286 assert.equal('$foo', render(vm))
287 })
288
289 it('not parse #[[ ]]#', function() {
290 var vm = '#foreach ($woogie in $boogie) nothing to $woogie #end'
291 assert.equal(vm, render('#[[' + vm + ']]#'))
292 })
293
294 it('Range Operator', function() {
295 var vm1 = '#set($foo = [-1..2])'
296 var vm2 = '#set($foo = [-1..$bar])'
297 var vm3 = '#set($foo = [$bar..2])'
298 assert.deepEqual([-1, 0, 1, 2], getContext(vm1).foo)
299 assert.deepEqual([-1, 0, 1, 2], getContext(vm2, {bar: 2}).foo)
300 assert.deepEqual([-1, 0, 1, 2], getContext(vm3, {bar: -1}).foo)
301 assert.deepEqual([], getContext('#set($foo = [$bar..1])').foo)
302 })
303
304 it('map and array nest', function() {
305 var vm1 = '' +
306 '#set($a = [\n' +
307 ' {"name": 1},\n' +
308 ' {"name": 2}\n' +
309 '])\n' +
310 ' '
311
312 var vm2 = '' +
313 '#set($a = {\n' +
314 ' "a": [1, 2, ["1", "a"], {"a": 1}],\n' +
315 ' "b": "12",\n' +
316 ' "d": null,\n' +
317 ' "c": false\n' +
318 '})\n' +
319 ''
320
321 assert.deepEqual([{name: 1}, { name: 2 }], getContext(vm1).a)
322 var expected = {
323 a: [1, 2, ["1", "a"], {a: 1}],
324 b: "12", d: null, c: false
325 };
326 assert.deepEqual(expected, getContext(vm2).a)
327 })
328 })
329
330 describe('Conditionals', function() {
331
332 it('#if', function() {
333 var vm = '#if($foo)Velocity#end'
334 assert.equal('Velocity', render(vm, {foo: 1}))
335 })
336
337 it('#if not work', function() {
338 var vm = '#if($!css_pureui)hello world#end'
339 assert.equal('', render(vm))
340 })
341
342 it('#elseif & #else', function() {
343 var vm = '#if($foo < 5)Go North#elseif($foo == 8)' +
344 'Go East#{else}Go South#end'
345 assert.equal('Go North', render(vm, {foo: 4}))
346 assert.equal('Go East', render(vm, {foo: 8}))
347 assert.equal('Go South', render(vm, {foo: 9}))
348 })
349
350 it('#if with arguments', function() {
351 var vm = '#if($foo.isTrue(true))true#{end}'
352 var foo = {
353 isTrue: function(str) {
354 return !!str
355 }
356 }
357
358 assert.equal('true', render(vm, {foo: foo}))
359 })
360
361 })
362
363 describe('Velocimacros', function() {
364
365 it('simple #macro', function() {
366 var vm = '#macro( d )<tr><td></td></tr>#end #d()'
367 assert.equal(' <tr><td></td></tr>', render(vm))
368 })
369
370 it('compex #macro', function() {
371 var vm = '#macro( d $name)<tr><td>$!name</td></tr>#end #d($foo)'
372 var vm1 = '#macro( d $a $b)#if($b)$a#end#end #d ( $foo $bar )'
373
374 assert.equal(' <tr><td>hanwen</td></tr>', render(vm, {foo: 'hanwen'}))
375 assert.equal(' <tr><td></td></tr>', render(vm))
376 assert.equal(' ', render(vm1, {foo: "haha"}))
377 assert.equal(' ', render(vm1, {foo: "haha", bar: false}))
378 assert.equal(' haha', render(vm1, {foo: "haha", bar: true}))
379 })
380
381 it('#macro call arguments', function() {
382 var vm = '#macro( d $a $b $d)$a$b$!d#end #d ( $foo , $bar, $dd )'
383 assert.equal(' ab', render(vm, {foo: 'a', bar: 'b'}))
384 assert.equal(' abd', render(vm, {foo: 'a', bar: 'b', dd: 'd'}))
385 })
386
387 it('#macro map argument', function() {
388 var vm = '#macro( d $a)#foreach($_item in $a.entrySet())' +
389 '$_item.key = $_item.value #end#end #d ( {"foo": $foo,"bar":$bar} )'
390 assert.equal(' foo = a bar = b ', render(vm, {foo: 'a', bar: 'b'}))
391 })
392
393 it('#noescape', function() {
394 var vm = '#noescape()$hello#end'
395 assert.equal('hello world', render(vm, {hello: 'hello world'}))
396 })
397
398 })
399
400 describe('Escaping', function() {
401 it('escape slash', function() {
402 var vm = '#set( $email = "foo" )$email \\$email'
403 assert.equal('foo $email', render(vm))
404 })
405
406 it('double slash', function() {
407 var vm = '#set( $email = "foo" )\\\\$email \\\\\\$email'
408 assert.equal("\\foo \\$email", render(vm))
409 })
410
411 })
412
413 describe('Error condiction', function() {
414
415 it('css color render', function() {
416 var vm = 'color: #666 height: 39px'
417 assert.equal(vm, render(vm))
418 })
419
420 it('jquery parse', function() {
421 var vm = '$(function() { $("a").click() $.post() })'
422 assert.equal(vm, render(vm))
423 })
424
425 it('issue #7: $ meet with #', function() {
426 var vm = '$bar.foo()#if(1>0)...#end'
427 assert.equal('$bar.foo()...', render(vm))
428 })
429
430 it('issue #15', function() {
431 var vm = '#macro(a $b $list)' +
432 '#foreach($a in $list)${a}#end $b #end #a("hello", [1, 2])'
433 assert.equal(' 12 hello ', render(vm))
434 })
435
436 it('issue #18', function() {
437 var vm = '$!tradeDetailModel.goodsInfoModel.goodsTitle' +
438 '[<a href="$!personalModule.setTarget(\'/p.htm\')' +
439 '.addQueryData("id",$!stringUtil.substringAfter' +
440 '($!tradeDetailModel.goodsInfoModel.goodsId,"guarantee."))"' +
441 ' target="_blank">商品页面</a>]'
442 var ret = '[<a href="" target="_blank">商品页面</a>]'
443 assert.equal(ret, render(vm))
444 })
445
446 it('issue #18, condiction 2', function() {
447 var vm = '$!a(**** **** **** $stringUtil.right($!b,4))'
448 var ret = '(**** **** **** $stringUtil.right($!b,4))'
449 assert.equal(ret, render(vm))
450 })
451
452 it('# meet with css property', function() {
453 var vm = '#margin-top:2px'
454 assert.equal(vm, render(vm))
455 })
456
457 it('var end must in condiction var begin', function() {
458 var vm = 'stepFareNo:{$!result.getStepFareNo()}'
459 assert.equal('stepFareNo:{}', render(vm))
460 })
461
462 it('empty string condiction', function() {
463 assert.equal('', render(''))
464 assert.equal('', render('##hello'))
465 assert.equal('hello', render('hello'))
466 })
467
468 })
469
470 describe('throw friendly error message', function() {
471 it('print right posiont when error throw', function() {
472 var vm = '111\nsdfs\n$foo($name)'
473
474 var compile = new Compile(parse(vm), { escape: false })
475 var context = {
476 name: '<i>',
477 foo: function() {
478 throw new Error('Run error')
479 }
480 }
481 assert.throws(function() {
482 compile.render(context)
483 }, /\$foo\(\$name\)/)
484
485 assert.throws(function() {
486 compile.render(context)
487 }, /L\/N 3:0/)
488 })
489
490 it('print error stack of user-defined macro', function() {
491 var vm = '111\n\n#foo($name)'
492 var vm1 = '\nhello#parse("vm.vm")'
493 var files = { 'vm.vm': vm, 'vm1.vm': vm1 };
494
495 var compile = new Compile(parse('\n\n#parse("vm1.vm")'))
496 var macros = {
497 foo: function() {
498 throw new Error('Run error')
499 },
500 parse: function(name) {
501 return this.eval(files[name]);
502 }
503 }
504
505 var expected = '' +
506 'Run error\n' +
507 ' at #foo($name) L/N 3:0\n' +
508 ' at #parse("vm.vm") L/N 2:5\n' +
509 ' at #parse("vm1.vm") L/N 3:0';
510 try {
511 compile.render({}, macros)
512 } catch (e) {
513 assert.equal(expected, e.message);
514 }
515 })
516 })
517
518 describe('user-defined macro, such as #include, #parse', function() {
519
520 it('basic', function() {
521 var macros = {
522 haha: function(a, b) {
523 a = a || ''
524 b = b || ''
525 return a + " hello to " + b
526 }
527 }
528
529 var vm = '#haha($a, $b)'
530 assert.equal(' hello to ', render(vm, {}, macros))
531 assert.equal('Lily hello to ', render(vm, {a: "Lily"}, macros))
532 })
533
534 it('use eval', function() {
535 var macros = {
536 cmsparse: function(str) {
537 return this.eval(str)
538 },
539 d: function() {
540 return 'I am d!'
541 }
542 }
543
544 var vm = '#cmsparse($str)'
545 var o = {
546 str: 'hello $foo.bar, #d()',
547 foo: {bar: 'world'}
548 }
549
550 assert.equal('hello world, I am d!', render(vm, o, macros))
551 })
552
553 it('use eval with local variable', function() {
554
555 var macros = {
556
557 cmsparse: function() {
558 return macros.include.apply(this, arguments)
559 },
560
561 include: function(str) {
562 return this.eval(str, {name: "hanwen"})
563 },
564
565 parse: function(file) {
566 return file
567 },
568
569 d: function() {
570 return this.eval('I am $name!')
571 }
572 }
573
574 var vm = '#cmsparse($str)'
575 var vm1 = '#parse("a.vm")'
576 var o = {
577 str: 'hello $foo.bar, #d()',
578 foo: {bar: 'world'}
579 }
580
581 assert.equal('hello world, I am hanwen!', render(vm, o, macros))
582 assert.equal(undefined, getContext(vm, o, macros).name)
583 assert.equal('a.vm', render(vm1, o, macros))
584 })
585
586 it('eval work with #set', function() {
587 var macros = {
588 cmsparse: function(str) {
589 return this.eval(str)
590 }
591 }
592
593 var vm = '#cmsparse($str)'
594 var o = {
595 str: '#set($foo = ["hello"," ", "world"])' +
596 '#foreach($word in $foo)$word#end'
597 }
598
599 assert.equal('hello world', render(vm, o, macros))
600 })
601 })
602
603
604 describe('self defined function', function() {
605
606 it('$control.setTemplate', function() {
607
608 var Control = function() {
609 this.__temp = {};
610 };
611
612 Control.prototype = {
613 constructor: Control,
614
615 setTemplate: function(vm) {
616
617 this.vm = vm;
618 return this;
619
620 },
621 toString: function() {
622 debugger;
623 return this.eval(this.vm, this.__temp);
624 },
625 setParameter: function(key, value) {
626 this.__temp[key] = value;
627 return this;
628 }
629 };
630
631 var str = 'hello $who, welcome to $where'
632
633 var vm = '$control.setTemplate($str).setParameter("who", "Blob")' +
634 '.setParameter("where", "China")'
635 var expected = 'hello Blob, welcome to China';
636 assert.equal(render(vm, {str: str, control: new Control()}), expected)
637
638 })
639
640 })
641
642 describe('issues', function() {
643 it('#29', function() {
644 var vm = '#set($total = 0) #foreach($i in [1,2,3])' +
645 ' #set($total = $total + $i) #end $total'
646 assert.equal(render(vm).trim(), "6")
647 })
648 it('#30', function() {
649 var vm = '$foo.setName'
650 assert.equal(render(vm, { foo: { setName: "foo" }}).trim(), "foo")
651 })
652 it('#54', function() {
653 var vm = '$a.b.c'
654 assert.equal(render(vm, { a: { b: null }}).trim(), "$a.b.c")
655
656 vm = '$a.b.c()'
657 assert.equal(render(vm, { a: { b: null }}).trim(), "$a.b.c()")
658 });
659 })
660
661 describe('multiline', function() {
662 it('#set multiline', function() {
663 var vm = "$bar.foo()\n#set($foo=$bar)\n..."
664 assert.equal("$bar.foo()\n...", render(vm))
665 })
666
667 it('#if multiline', function() {
668 var vm = "$bar.foo()\n#if(1>0)\n...#end"
669 assert.equal("$bar.foo()\n...", render(vm))
670 })
671
672 it('#set #set', function() {
673 var vm = "$bar.foo()\n...\n#set($foo=$bar)\n#set($foo=$bar)"
674 assert.equal("$bar.foo()\n...\n", render(vm))
675 })
676
677 it('#if multiline #set', function() {
678 var vm = "$bar.foo()\n#if(1>0)\n#set($foo=$bar)\n...#end"
679 assert.equal("$bar.foo()\n...", render(vm))
680 })
681
682 it('#if multiline #set #end', function() {
683 var vm = "$bar.foo()\n#if(1>0)...\n#set($foo=$bar)\n#end"
684 assert.equal("$bar.foo()\n...\n", render(vm))
685 })
686
687 it('with references', function() {
688 var vm = ['a',
689 '#foreach($b in $nums)',
690 '#if($b) ',
691 'b',
692 'e $b.alm',
693 '#end',
694 '#end',
695 'c'].join("\n");
696 var expected = ['a', 'b', 'e 1', 'b', 'e 2', 'b', 'e 3', 'c'].join("\n")
697
698 var data = {nums:[{alm:1}, {alm:2}, {alm:3}], bar:""};
699 assert.equal(expected, render(vm, data))
700 })
701
702 it('multiple newlines after statement', function() {
703 var vm = '#if(1>0)\n\nb#end'
704 assert.equal('\nb', render(vm))
705 })
706 })
707
708 describe('define support', function() {
709 it('basic', function() {
710 var vm = '#define($block)\nHello $who#end\n#set($who = "World!")\n$block'
711 assert.equal('Hello World!', render(vm))
712 })
713 })
714
715 describe('raw content render', function() {
716 it('simple', function() {
717 var vm = '#[[\nThis content is ignored. $val\n]]#';
718 assert.equal('\nThis content is ignored. $val\n', render(vm, {
719 val: 'foo'
720 }));
721 });
722
723 it('newline after', function() {
724 var vm = '#[[This content is ignored. $val]]#\na';
725 assert.equal('This content is ignored. $val\na', render(vm, {
726 val: 'foo'
727 }));
728 });
729 });
730
731 describe('assignment via .put', function () {
732 it('should set a key to an object', function() {
733 var vm = `
734 #set($foo = {})
735 #set($test = $foo.put('foo', 'bar'))
736 $foo["foo"]
737 `;
738 var expected = 'bar';
739 assert.equal(render(vm).trim(), expected)
740 });
741 it('fix issue #120, push only', function() {
742 var vm = `
743 #set($foo = {})
744 $!{ foo.put("a", 1) }
745 `;
746 var expected = '1';
747 assert.equal(render(vm).trim(), expected)
748 });
749 it('should set a key to an object', function() {
750 var vm = `
751 $foo.put()
752 `;
753 var expected = 'bar';
754 assert.equal(render(vm, {
755 foo: {
756 put: function() {
757 return 'bar';
758 }
759 }
760 }).trim(), expected)
761 });
762 });
763
764 describe('deletion via .remove', function () {
765 it('should remove a key from an object', function() {
766 var vm = `
767 #set($test = {'foo': 'bar'})
768 #set($baz = $test.remove('foo'))
769 $test
770 `;
771 var expected = '{}';
772 assert.equal(render(vm).trim(), expected);
773 });
774
775 it('should return the value of the removed key', function () {
776 var vm = `
777 #set($test = {'foo': 'bar'})
778 #set($baz = $test.remove('foo'))
779 $baz
780 `;
781 var expected = 'bar';
782 assert.equal(render(vm).trim(), expected);
783 });
784
785 it('should remove a value from an array', function () {
786 var vm = `
787 #set($test = ['foo', 'bar'])
788 #set($baz = $test.remove('bar'))
789 $test
790 `;
791 var expected = '[foo]';
792 assert.equal(render(vm).trim(), expected);
793 });
794
795 it('should return the removed value', function () {
796 var vm = `
797 #set($test = ['foo', 'bar'])
798 #set($baz = $test.remove('bar'))
799 $baz
800 `;
801 var expected = 'bar';
802 assert.equal(render(vm).trim(), expected);
803 });
804 });
805
806 describe('Add into empty array', function () {
807 it('should add item to array', function() {
808 var vm = `
809 #set($foo = [])
810 #set($ignore = $foo.add('foo'))
811 $foo
812 `;
813 var expected = '[foo]';
814 assert.equal(render(vm).trim(), expected)
815 });
816
817 it('should add object to array', function() {
818 var vm = `
819 #set($foo = [])
820 #set($ignore = $foo.add({'foo':'bar'}))
821 $foo
822 `;
823 var expected = '[{foo=bar}]';
824 assert.equal(render(vm).trim(), expected)
825 });
826
827 it('should not add when is object', function() {
828 var vm = `
829 #set($foo = {})
830 #set($ignore = $foo.add({'foo':'bar'}))
831 $foo
832 `;
833 var expected = '{}';
834 assert.equal(render(vm).trim(), expected)
835 });
836 });
837
838 describe('extracting items via .subList', function() {
839 it('should return empty array if original array is empty', function() {
840 var vm = `
841 #set($foo = [])
842 #set($bar = $foo.subList(0, 1))
843 $bar
844 `;
845 var expected = '[]';
846 assert.equal(render(vm).trim(), expected)
847 });
848
849 it('should return a single item', function() {
850 var vm = `
851 #set($foo = [1, 2, 3])
852 #set($bar = $foo.subList(0, 1))
853 $bar
854 `;
855 var expected = '[1]';
856 assert.equal(render(vm).trim(), expected)
857 });
858
859 it('should return multiple items', function() {
860 var vm = `
861 #set($foo = [1, 2, 3])
862 #set($bar = $foo.subList(1, 3))
863 $bar
864 `;
865 var expected = '[2, 3]';
866 assert.equal(render(vm).trim(), expected)
867 });
868 });
869
870 describe('Object|Array#toString', function() {
871 it('simple object', function() {
872 var vm = '$data';
873 var expected = '{k=v, k2=v2}';
874 assert.equal(render(vm, {data: {k: "v", k2: "v2"}}), expected)
875 });
876
877 it('object.keySet()', function() {
878 var vm = '$data.keySet()';
879 var expected = '[k, k2]';
880 assert.equal(render(vm, {data: {k: "v", k2: "v2"}}), expected)
881 });
882
883 it('object.keySet() with object that has keySet method', function() {
884 var vm = '$data.keySet()';
885 var expected = '[k, k2]';
886 function keySet() {
887 return ['k', 'k2'];
888 }
889 assert.equal(render(vm, {data: { keySet: keySet }}), expected)
890 });
891
892 it('object.entrySet()', function() {
893 var vm = '$data.entrySet()';
894 var expected = '[{key=k, value=v}, {key=k2, value=v2}]';
895 assert.equal(render(vm, {data: {k: "v", k2: "v2"}}), expected)
896 });
897
898 it('object.entrySet() with object that has entrySet method', function() {
899 var vm = '$data.entrySet()';
900 var expected = '{k=v, k2=v2}';
901
902 function entrySet() {
903 return {
904 k: "v", k2: "v2"
905 }
906 }
907
908 assert.equal(render(vm, {data: { entrySet: entrySet }}), expected)
909 });
910
911 it('nested object', function() {
912 var vm = '$data';
913 var expected = '{k={k2=v2}, kk={k3=v3}}';
914 assert.equal(render(vm, {data: {k: {k2: "v2"}, kk: {k3: "v3"}}}), expected)
915 });
916
917 it('object that has toString as own property', function() {
918 var vm = '$data';
919 var expected = 'custom';
920 assert.equal(render(vm, {data: {toString: function() { return 'custom'; }, key: "value", key2: "value2", key3: {key4: "value4"}}}), expected)
921 });
922
923 it('simple array', function() {
924 var vm = '$data';
925 var expected = '[a, b]';
926 assert.equal(render(vm, {data: ["a", "b"]}), expected)
927 });
928
929 it('nested array', function() {
930 var vm = '$data';
931 var expected = '[a, [b]]';
932 assert.equal(render(vm, {data: ["a", ["b"]]}), expected)
933 });
934
935 it('object in array', function() {
936 var vm = '$data';
937 var expected = '[a, {k=v}]';
938 assert.equal(render(vm, {data: ["a", {k: "v"}]}), expected)
939 });
940
941 it('array in object', function() {
942 var vm = '$data';
943 var expected = '{k=[a, b]}';
944 assert.equal(render(vm, {data: {k: ["a", "b"]}}), expected)
945 });
946 });
947})
948