1#============================================================= -*-perl-*- 2# 3# t/view.t 4# 5# Tests the 'View' plugin. 6# 7# Written by Andy Wardley <abw@kfs.org> 8# 9# Copyright (C) 2000 Andy Wardley. All Rights Reserved. 10# 11# This is free software; you can redistribute it and/or modify it 12# under the same terms as Perl itself. 13# 14# $Id$ 15# 16#======================================================================== 17 18use strict; 19use lib qw( ./lib ../lib ); 20use Template::Test; 21$^W = 1; 22 23use Template::View; 24 25#$Template::View::DEBUG = 1; 26#$Template::Test::DEBUG = 0; 27#$Template::Parser::DEBUG = 1; 28#$Template::Directive::PRETTY = 1; 29$Template::Test::PRESERVE = 1; 30 31#------------------------------------------------------------------------ 32package Foo; 33 34sub new { 35 my $class = shift; 36 bless { @_ }, $class; 37} 38 39sub present { 40 my $self = shift; 41 return '{ ' . join(', ', map { "$_ => $self->{ $_ }" } 42 sort keys %$self) . ' }'; 43} 44 45sub reverse { 46 my $self = shift; 47 return '{ ' . join(', ', map { "$_ => $self->{ $_ }" } 48 reverse sort keys %$self) . ' }'; 49} 50 51#------------------------------------------------------------------------ 52package Blessed::List; 53 54sub as_list { 55 my $self = shift; 56 return @$self; 57} 58 59#------------------------------------------------------------------------ 60package main; 61 62my $vars = { 63 foo => Foo->new( pi => 3.14, e => 2.718 ), 64 blessed_list => bless([ "Hello", "World" ], 'Blessed::List'), 65}; 66 67my $template = Template->new() || die Template->error; 68my $context = $template->context(); 69my $view = $context->view( ); 70ok( $view ); 71 72$view = $context->view( prefix => 'my' ); 73ok( $view ); 74match( $view->prefix(), 'my' ); 75 76my $config = { 77 VIEWS => [ 78 bottom => { prefix => 'bottom/' }, 79 middle => { prefix => 'middle/', base => 'bottom' }, 80 ], 81}; 82 83test_expect(\*DATA, $config, $vars); 84 85__DATA__ 86-- test -- 87-- name pre-defined bottom view -- 88[% BLOCK bottom/list; "BOTTOM LIST: "; item.join(', '); END; 89 list = [10, 20 30]; 90 bottom.print(list) 91%] 92-- expect -- 93BOTTOM LIST: 10, 20, 30 94 95-- test -- 96-- name pre-defined middle view -- 97[% BLOCK bottom/list; "BOTTOM LIST: "; item.join(', '); END; 98 BLOCK middle/hash; "MIDDLE HASH: "; item.values.nsort.join(', '); END; 99 list = [10, 20 30]; 100 hash = { pi => 3.142, e => 2.718 }; 101 middle.print(list); "\n"; 102 middle.print(hash); "\n"; 103%] 104-- expect -- 105BOTTOM LIST: 10, 20, 30 106MIDDLE HASH: 2.718, 3.142 107 108-- test -- 109[% USE v = View -%] 110[[% v.prefix %]] 111-- expect -- 112[] 113 114-- test -- 115[% USE v = View( map => { default="any" } ) -%] 116[[% v.map.default %]] 117-- expect -- 118[any] 119 120-- test -- 121[% USE view( prefix=> 'foo/', suffix => '.tt2') -%] 122[[% view.prefix %]bar[% view.suffix %]] 123[[% view.template_name('baz') %]] 124-- expect -- 125[foo/bar.tt2] 126[foo/baz.tt2] 127 128-- test -- 129[% USE view( prefix=> 'foo/', suffix => '.tt2') -%] 130[[% view.prefix %]bar[% view.suffix %]] 131[[% view.template_name('baz') %]] 132-- expect -- 133[foo/bar.tt2] 134[foo/baz.tt2] 135 136-- test -- 137[% USE view -%] 138[% view.print('Hello World') %] 139[% BLOCK text %]TEXT: [% item %][% END -%] 140-- expect -- 141TEXT: Hello World 142 143-- test -- 144[% USE view -%] 145[% view.print( { foo => 'bar' } ) %] 146[% BLOCK hash %]HASH: { 147[% FOREACH key = item.keys.sort -%] 148 [% key %] => [% item.$key %] 149[%- END %] 150} 151[% END -%] 152-- expect -- 153HASH: { 154 foo => bar 155} 156 157-- test -- 158[% USE view -%] 159[% view = view.clone( prefix => 'my_' ) -%] 160[% view.view('hash', { bar => 'baz' }) %] 161[% BLOCK my_hash %]HASH: { 162[% FOREACH key = item.keys.sort -%] 163 [% key %] => [% item.$key %] 164[%- END %] 165} 166[% END -%] 167-- expect -- 168HASH: { 169 bar => baz 170} 171 172 173-- test -- 174[% USE view(prefix='my_') -%] 175[% view.print( foo => 'wiz', bar => 'waz' ) %] 176[% BLOCK my_hash %]KEYS: [% item.keys.sort.join(', ') %][% END %] 177 178-- expect -- 179KEYS: bar, foo 180 181-- test -- 182[% USE view -%] 183[% view.print( view ) %] 184[% BLOCK Template_View %]Printing a Template::View object[% END -%] 185-- expect -- 186Printing a Template::View object 187 188-- test -- 189[% USE view(prefix='my_') -%] 190[% view.print( view ) %] 191[% view.print( view, prefix='your_' ) %] 192[% BLOCK my_Template_View %]Printing my Template::View object[% END -%] 193[% BLOCK your_Template_View %]Printing your Template::View object[% END -%] 194-- expect -- 195Printing my Template::View object 196Printing your Template::View object 197 198-- test -- 199[% USE view(prefix='my_', notfound='any' ) -%] 200[% view.print( view ) %] 201[% view.print( view, prefix='your_' ) %] 202[% BLOCK my_any %]Printing any of my objects[% END -%] 203[% BLOCK your_any %]Printing any of your objects[% END -%] 204-- expect -- 205Printing any of my objects 206Printing any of your objects 207 208-- test -- 209[% USE view(prefix => 'my_', map => { default => 'catchall' } ) -%] 210[% view.print( view ) %] 211[% view.print( view, default="catchsome" ) %] 212[% BLOCK my_catchall %]Catching all defaults[% END -%] 213[% BLOCK my_catchsome %]Catching some defaults[% END -%] 214-- expect -- 215Catching all defaults 216Catching some defaults 217 218-- test -- 219[% USE view(prefix => 'my_', map => { default => 'catchnone' } ) -%] 220[% view.default %] 221[% view.default = 'catchall' -%] 222[% view.default %] 223[% view.print( view ) %] 224[% view.print( view, default="catchsome" ) %] 225[% BLOCK my_catchall %]Catching all defaults[% END -%] 226[% BLOCK my_catchsome %]Catching some defaults[% END -%] 227-- expect -- 228catchnone 229catchall 230Catching all defaults 231Catching some defaults 232 233-- test -- 234[% USE view(prefix='my_', default='catchall' notfound='lost') -%] 235[% view.print( view ) %] 236[% BLOCK my_lost %]Something has been found[% END -%] 237-- expect -- 238Something has been found 239 240-- test -- 241[% USE view -%] 242[% TRY ; 243 view.print( view ) ; 244 CATCH view ; 245 "[$error.type] $error.info" ; 246 END 247%] 248-- expect -- 249[view] file error - Template_View: not found 250 251 252-- test -- 253[% USE view -%] 254[% view.print( foo ) %] 255-- expect -- 256{ e => 2.718, pi => 3.14 } 257 258-- test -- 259[% USE view -%] 260[% view.print( foo, method => 'reverse' ) %] 261-- expect -- 262{ pi => 3.14, e => 2.718 } 263 264-- test -- 265[% USE view(prefix='my_', include_naked=0, view_naked=1) -%] 266[% BLOCK my_foo; "Foo: $item"; END -%] 267[[% view.view_foo(20) %]] 268[[% view.foo(30) %]] 269-- expect -- 270[Foo: 20] 271[Foo: 30] 272 273-- test -- 274[% USE view(prefix='my_', include_naked=0, view_naked=0) -%] 275[% BLOCK my_foo; "Foo: $item"; END -%] 276[[% view.view_foo(20) %]] 277[% TRY ; 278 view.foo(30) ; 279 CATCH ; 280 error.info ; 281 END 282%] 283-- expect -- 284[Foo: 20] 285no such view member: foo 286 287-- test -- 288[% USE view(map => { HASH => 'my_hash', ARRAY => 'your_list' }) -%] 289[% BLOCK text %]TEXT: [% item %][% END -%] 290[% BLOCK my_hash %]HASH: [% item.keys.sort.join(', ') %][% END -%] 291[% BLOCK your_list %]LIST: [% item.join(', ') %][% END -%] 292[% view.print("some text") %] 293[% view.print({ alpha => 'a', bravo => 'b' }) %] 294[% view.print([ 'charlie', 'delta' ]) %] 295-- expect -- 296TEXT: some text 297HASH: alpha, bravo 298LIST: charlie, delta 299 300-- test -- 301[% USE view(item => 'thing', 302 map => { HASH => 'my_hash', ARRAY => 'your_list' }) -%] 303[% BLOCK text %]TEXT: [% thing %][% END -%] 304[% BLOCK my_hash %]HASH: [% thing.keys.sort.join(', ') %][% END -%] 305[% BLOCK your_list %]LIST: [% thing.join(', ') %][% END -%] 306[% view.print("some text") %] 307[% view.print({ alpha => 'a', bravo => 'b' }) %] 308[% view.print([ 'charlie', 'delta' ]) %] 309-- expect -- 310TEXT: some text 311HASH: alpha, bravo 312LIST: charlie, delta 313 314-- test -- 315[% USE view -%] 316[% view.print('Hello World') %] 317[% view1 = view.clone( prefix='my_') -%] 318[% view1.print('Hello World') %] 319[% view2 = view1.clone( prefix='dud_', notfound='no_text' ) -%] 320[% view2.print('Hello World') %] 321[% BLOCK text %]TEXT: [% item %][% END -%] 322[% BLOCK my_text %]MY TEXT: [% item %][% END -%] 323[% BLOCK dud_no_text %]NO TEXT: [% item %][% END -%] 324-- expect -- 325TEXT: Hello World 326MY TEXT: Hello World 327NO TEXT: Hello World 328 329-- test -- 330[% USE view( prefix = 'base_', default => 'any' ) -%] 331[% view1 = view.clone( prefix => 'one_') -%] 332[% view2 = view.clone( prefix => 'two_') -%] 333[% view.default %] / [% view.map.default %] 334[% view1.default = 'anyone' -%] 335[% view1.default %] / [% view1.map.default %] 336[% view2.map.default = 'anytwo' -%] 337[% view2.default %] / [% view2.map.default %] 338[% view.print("Hello World") %] / [% view.print(blessed_list) %] 339[% view1.print("Hello World") %] / [% view1.print(blessed_list) %] 340[% view2.print("Hello World") %] / [% view2.print(blessed_list) %] 341[% BLOCK base_text %]ANY TEXT: [% item %][% END -%] 342[% BLOCK one_text %]ONE TEXT: [% item %][% END -%] 343[% BLOCK two_text %]TWO TEXT: [% item %][% END -%] 344[% BLOCK base_any %]BASE ANY: [% item.as_list.join(', ') %][% END -%] 345[% BLOCK one_anyone %]ONE ANY: [% item.as_list.join(', ') %][% END -%] 346[% BLOCK two_anytwo %]TWO ANY: [% item.as_list.join(', ') %][% END -%] 347-- expect -- 348any / any 349anyone / anyone 350anytwo / anytwo 351ANY TEXT: Hello World / BASE ANY: Hello, World 352ONE TEXT: Hello World / ONE ANY: Hello, World 353TWO TEXT: Hello World / TWO ANY: Hello, World 354 355-- test -- 356[% USE view( prefix => 'my_', item => 'thing' ) -%] 357[% view.view('thingy', [ 'foo', 'bar'] ) %] 358[% BLOCK my_thingy %]thingy: [ [% thing.join(', ') %] ][%END %] 359-- expect -- 360thingy: [ foo, bar ] 361 362-- test -- 363[% USE view -%] 364[% view.map.${'Template::View'} = 'myview' -%] 365[% view.print(view) %] 366[% BLOCK myview %]MYVIEW[% END%] 367-- expect -- 368MYVIEW 369 370-- test -- 371[% USE view -%] 372[% view.include('greeting', msg => 'Hello World!') %] 373[% BLOCK greeting %]msg: [% msg %][% END -%] 374-- expect -- 375msg: Hello World! 376 377-- test -- 378[% USE view( prefix="my_" )-%] 379[% view.include('greeting', msg => 'Hello World!') %] 380[% BLOCK my_greeting %]msg: [% msg %][% END -%] 381-- expect -- 382msg: Hello World! 383 384-- test -- 385[% USE view( prefix="my_" )-%] 386[% view.include_greeting( msg => 'Hello World!') %] 387[% BLOCK my_greeting %]msg: [% msg %][% END -%] 388-- expect -- 389msg: Hello World! 390 391-- test -- 392[% USE view( prefix="my_" )-%] 393[% INCLUDE $view.template('greeting') 394 msg = 'Hello World!' %] 395[% BLOCK my_greeting %]msg: [% msg %][% END -%] 396-- expect -- 397msg: Hello World! 398 399-- test -- 400[% USE view( title="My View" )-%] 401[% view.title %] 402-- expect -- 403My View 404 405-- test -- 406[% USE view( title="My View" )-%] 407[% newview = view.clone( col = 'Chartreuse') -%] 408[% newerview = newview.clone( title => 'New Title' ) -%] 409[% view.title %] 410[% newview.title %] 411[% newview.col %] 412[% newerview.title %] 413[% newerview.col %] 414-- expect -- 415My View 416My View 417Chartreuse 418New Title 419Chartreuse 420 421 422#------------------------------------------------------------------------ 423 424-- test -- 425[% VIEW fred prefix='blat_' %] 426This is the view 427[% END -%] 428[% BLOCK blat_foo; 'This is blat_foo'; END -%] 429[% fred.view_foo %] 430-- expect -- 431This is blat_foo 432 433-- test -- 434[% VIEW fred %] 435This is the view 436[% view.prefix = 'blat_' %] 437[% END -%] 438[% BLOCK blat_foo; 'This is blat_foo'; END -%] 439[% fred.view_foo %] 440-- expect -- 441This is blat_foo 442 443-- test -- 444[% VIEW fred %] 445This is the view 446[% view.prefix = 'blat_' %] 447[% view.thingy = 'bloop' %] 448[% fred.name = 'Freddy' %] 449[% END -%] 450[% fred.prefix %] 451[% fred.thingy %] 452[% fred.name %] 453-- expect -- 454blat_ 455bloop 456Freddy 457 458 459-- test -- 460[% VIEW fred prefix='blat_'; view.name='Fred'; END -%] 461[% fred.prefix %] 462[% fred.name %] 463[% TRY; 464 fred.prefix = 'nonblat_'; 465 CATCH; 466 error; 467 END 468%] 469[% TRY; 470 fred.name = 'Derek'; 471 CATCH; 472 error; 473 END 474%] 475-- expect -- 476blat_ 477Fred 478view error - cannot update config item in sealed view: prefix 479view error - cannot update item in sealed view: name 480 481-- test -- 482[% VIEW foo prefix='blat_' default="default" notfound="notfound" 483 title="fred" age=23 height=1.82 %] 484[% view.other = 'another' %] 485[% END -%] 486[% BLOCK blat_hash -%] 487[% FOREACH key = item.keys.sort -%] 488 [% key %] => [% item.$key %] 489[% END -%] 490[% END -%] 491[% foo.print(foo.data) %] 492-- expect -- 493 age => 23 494 height => 1.82 495 other => another 496 title => fred 497 498-- test -- 499[% VIEW foo %] 500[% BLOCK hello -%] 501Hello World! 502[% END %] 503[% BLOCK goodbye -%] 504Goodbye World! 505[% END %] 506[% END -%] 507[% TRY; INCLUDE foo; CATCH; error; END %] 508[% foo.include_hello %] 509-- expect -- 510file error - foo: not found 511Hello World! 512 513-- test -- 514[% title = "Previous Title" -%] 515[% VIEW foo 516 include_naked = 1 517 title = title or 'Default Title' 518 copy = 'me, now' 519-%] 520 521[% view.bgcol = '#ffffff' -%] 522 523[% BLOCK header -%] 524Header: bgcol: [% view.bgcol %] 525 title: [% title %] 526 view.title: [% view.title %] 527[%- END %] 528 529[% BLOCK footer -%] 530© Copyright [% view.copy %] 531[%- END %] 532 533[% END -%] 534[% title = 'New Title' -%] 535[% foo.header %] 536[% foo.header(bgcol='#dead' title="Title Parameter") %] 537[% foo.footer %] 538[% foo.footer(copy="you, then") %] 539 540-- expect -- 541Header: bgcol: #ffffff 542 title: New Title 543 view.title: Previous Title 544Header: bgcol: #ffffff 545 title: Title Parameter 546 view.title: Previous Title 547© Copyright me, now 548© Copyright me, now 549 550-- test -- 551[% VIEW foo 552 title = 'My View' 553 author = 'Andy Wardley' 554 bgcol = bgcol or '#ffffff' 555-%] 556[% view.arg1 = 'argument #1' -%] 557[% view.data.arg2 = 'argument #2' -%] 558[% END -%] 559 [% foo.title %] 560 [% foo.author %] 561 [% foo.bgcol %] 562 [% foo.arg1 %] 563 [% foo.arg2 %] 564[% bar = foo.clone( title='New View', arg1='New Arg1' ) %]cloned! 565 [% bar.title %] 566 [% bar.author %] 567 [% bar.bgcol %] 568 [% bar.arg1 %] 569 [% bar.arg2 %] 570originals: 571 [% foo.title %] 572 [% foo.arg1 %] 573 574 575-- expect -- 576 My View 577 Andy Wardley 578 #ffffff 579 argument #1 580 argument #2 581cloned! 582 New View 583 Andy Wardley 584 #ffffff 585 New Arg1 586 argument #2 587originals: 588 My View 589 argument #1 590 591 592-- test -- 593[% VIEW basic title = "My Web Site" %] 594 [% BLOCK header -%] 595 This is the basic header: [% title or view.title %] 596 [%- END -%] 597[% END -%] 598 599[%- VIEW fancy 600 title = "<fancy>$basic.title</fancy>" 601 basic = basic 602%] 603 [% BLOCK header ; view.basic.header(title = title or view.title) %] 604 Fancy new part of header 605 [%- END %] 606[% END -%] 607=== 608[% basic.header %] 609[% basic.header( title = "New Title" ) %] 610=== 611[% fancy.header %] 612[% fancy.header( title = "Fancy Title" ) %] 613-- expect -- 614=== 615 This is the basic header: My Web Site 616 This is the basic header: New Title 617=== 618 This is the basic header: <fancy>My Web Site</fancy> 619 Fancy new part of header 620 This is the basic header: Fancy Title 621 Fancy new part of header 622 623-- test -- 624[% VIEW baz notfound='lost' %] 625[% BLOCK lost; 'lost, not found'; END %] 626[% END -%] 627[% baz.any %] 628-- expect -- 629lost, not found 630 631-- test -- 632[% VIEW woz prefix='outer_' %] 633[% BLOCK wiz; 'The inner wiz'; END %] 634[% END -%] 635[% BLOCK outer_waz; 'The outer waz'; END -%] 636[% woz.wiz %] 637[% woz.waz %] 638-- expect -- 639The inner wiz 640The outer waz 641 642-- test -- 643[% VIEW foo %] 644 645 [% BLOCK file -%] 646 File: [% item.name %] 647 [%- END -%] 648 649 [% BLOCK directory -%] 650 Dir: [% item.name %] 651 [%- END %] 652 653[% END -%] 654[% foo.view_file({ name => 'some_file' }) %] 655[% foo.include_file(item => { name => 'some_file' }) %] 656[% foo.view('directory', { name => 'some_dir' }) %] 657-- expect -- 658 File: some_file 659 File: some_file 660 Dir: some_dir 661 662-- test -- 663[% BLOCK parent -%] 664This is the base block 665[%- END -%] 666[% VIEW super %] 667 [%- BLOCK parent -%] 668 [%- INCLUDE parent | replace('base', 'super') -%] 669 [%- END -%] 670[% END -%] 671base: [% INCLUDE parent %] 672super: [% super.parent %] 673-- expect -- 674base: This is the base block 675super: This is the super block 676 677-- test -- 678[% BLOCK foo -%] 679public foo block 680[%- END -%] 681[% VIEW plain %] 682 [% BLOCK foo -%] 683<plain>[% PROCESS foo %]</plain> 684 [%- END %] 685[% END -%] 686[% VIEW fancy %] 687 [% BLOCK foo -%] 688 [%- plain.foo | replace('plain', 'fancy') -%] 689 [%- END %] 690[% END -%] 691[% plain.foo %] 692[% fancy.foo %] 693-- expect -- 694<plain>public foo block</plain> 695<fancy>public foo block</fancy> 696 697-- test -- 698[% VIEW foo %] 699[% BLOCK Blessed_List -%] 700This is a list: [% item.as_list.join(', ') %] 701[% END -%] 702[% END -%] 703[% foo.print(blessed_list) %] 704-- expect -- 705This is a list: Hello, World 706 707-- test -- 708[% VIEW my.foo value=33; END -%] 709n: [% my.foo.value %] 710-- expect -- 711n: 33 712 713-- test -- 714[% VIEW parent -%] 715[% BLOCK one %]This is base one[% END %] 716[% BLOCK two %]This is base two[% END %] 717[% END -%] 718 719[%- VIEW child1 base=parent %] 720[% BLOCK one %]This is child1 one[% END %] 721[% END -%] 722 723[%- VIEW child2 base=parent %] 724[% BLOCK two %]This is child2 two[% END %] 725[% END -%] 726 727[%- VIEW child3 base=child2 %] 728[% BLOCK two %]This is child3 two[% END %] 729[% END -%] 730 731[%- FOREACH child = [ child1, child2, child3 ] -%] 732one: [% child.one %] 733[% END -%] 734[% FOREACH child = [ child1, child2, child3 ] -%] 735two: [% child.two %] 736[% END %] 737 738-- expect -- 739one: This is child1 one 740one: This is base one 741one: This is base one 742two: This is base two 743two: This is child2 two 744two: This is child3 two 745 746-- test -- 747[% VIEW my.view.default 748 prefix = 'view/default/' 749 value = 3.14; 750 END 751-%] 752value: [% my.view.default.value %] 753-- expect -- 754value: 3.14 755 756-- test -- 757[% VIEW my.view.default 758 prefix = 'view/default/' 759 value = 3.14; 760 END; 761 VIEW my.view.one 762 base = my.view.default 763 prefix = 'view/one/'; 764 END; 765 VIEW my.view.two 766 base = my.view.default 767 value = 2.718; 768 END; 769-%] 770[% BLOCK view/default/foo %]Default foo[% END -%] 771[% BLOCK view/one/foo %]One foo[% END -%] 7720: [% my.view.default.foo %] 7731: [% my.view.one.foo %] 7742: [% my.view.two.foo %] 7750: [% my.view.default.value %] 7761: [% my.view.one.value %] 7772: [% my.view.two.value %] 778-- expect -- 7790: Default foo 7801: One foo 7812: Default foo 7820: 3.14 7831: 3.14 7842: 2.718 785 786-- test -- 787[% VIEW foo number = 10 sealed = 0; END -%] 788a: [% foo.number %] 789b: [% foo.number = 20 %] 790c: [% foo.number %] 791d: [% foo.number(30) %] 792e: [% foo.number %] 793-- expect -- 794a: 10 795b: 796c: 20 797d: 30 798e: 30 799 800-- test -- 801[% VIEW foo number = 10 silent = 1; END -%] 802a: [% foo.number %] 803b: [% foo.number = 20 %] 804c: [% foo.number %] 805d: [% foo.number(30) %] 806e: [% foo.number %] 807-- expect -- 808a: 10 809b: 810c: 10 811d: 10 812e: 10 813 814-- test -- 815-- name bad base -- 816[% TRY; 817 VIEW wiz base=no_such_base_at_all; 818 END; 819 CATCH; 820 error; 821 END 822-%] 823-- expect -- 824view error - Invalid base specified for view 825