[Catalyst-commits] r11510 - in Catalyst-View-TD: . trunk trunk/lib trunk/lib/Catalyst trunk/lib/Catalyst/Helper trunk/lib/Catalyst/Helper/View trunk/lib/Catalyst/View trunk/t trunk/t/lib trunk/t/lib/TestApp trunk/t/lib/TestApp/TD trunk/t/lib/TestApp/Template trunk/t/lib/TestApp/View

theory at dev.catalyst.perl.org theory at dev.catalyst.perl.org
Fri Oct 9 06:19:26 GMT 2009


Author: theory
Date: 2009-10-09 06:19:26 +0000 (Fri, 09 Oct 2009)
New Revision: 11510

Added:
   Catalyst-View-TD/trunk/
   Catalyst-View-TD/trunk/Changes
   Catalyst-View-TD/trunk/MANIFEST.SKIP
   Catalyst-View-TD/trunk/Makefile.PL
   Catalyst-View-TD/trunk/lib/
   Catalyst-View-TD/trunk/lib/Catalyst/
   Catalyst-View-TD/trunk/lib/Catalyst/Helper/
   Catalyst-View-TD/trunk/lib/Catalyst/Helper/View/
   Catalyst-View-TD/trunk/lib/Catalyst/Helper/View/TD.pm
   Catalyst-View-TD/trunk/lib/Catalyst/View/
   Catalyst-View-TD/trunk/lib/Catalyst/View/TD.pm
   Catalyst-View-TD/trunk/t/
   Catalyst-View-TD/trunk/t/01use.t
   Catalyst-View-TD/trunk/t/02pod.t
   Catalyst-View-TD/trunk/t/03podcoverage.t
   Catalyst-View-TD/trunk/t/04pkgconfig.t
   Catalyst-View-TD/trunk/t/05appconfig.t
   Catalyst-View-TD/trunk/t/06includepath.t
   Catalyst-View-TD/trunk/t/07render.t
   Catalyst-View-TD/trunk/t/08cycle.t
   Catalyst-View-TD/trunk/t/11norequest.t
   Catalyst-View-TD/trunk/t/lib/
   Catalyst-View-TD/trunk/t/lib/TestApp.pm
   Catalyst-View-TD/trunk/t/lib/TestApp/
   Catalyst-View-TD/trunk/t/lib/TestApp/TD/
   Catalyst-View-TD/trunk/t/lib/TestApp/TD/Appconfig.pm
   Catalyst-View-TD/trunk/t/lib/TestApp/Template/
   Catalyst-View-TD/trunk/t/lib/TestApp/Template/Pkgconfig.pm
   Catalyst-View-TD/trunk/t/lib/TestApp/View/
   Catalyst-View-TD/trunk/t/lib/TestApp/View/Appconfig.pm
   Catalyst-View-TD/trunk/t/lib/TestApp/View/Pkgconfig.pm
Log:
First stab at new Template::Declare view. I copied most of the code from
View::TT. There are way too few tests! Over the next week, I'll get things
working really well, including support for modifying template roots at
runtime. I'll also add a lot more tests. All the relevant tests copied from
View::TT pass (all 29 of them).



Added: Catalyst-View-TD/trunk/Changes
===================================================================
--- Catalyst-View-TD/trunk/Changes	                        (rev 0)
+++ Catalyst-View-TD/trunk/Changes	2009-10-09 06:19:26 UTC (rev 11510)
@@ -0,0 +1,4 @@
+Revision history for Perl extension Catalyst::View::TD.
+
+0.01    XXXX-XX-XX
+        - first release

Added: Catalyst-View-TD/trunk/MANIFEST.SKIP
===================================================================
--- Catalyst-View-TD/trunk/MANIFEST.SKIP	                        (rev 0)
+++ Catalyst-View-TD/trunk/MANIFEST.SKIP	2009-10-09 06:19:26 UTC (rev 11510)
@@ -0,0 +1,34 @@
+# Avoid version control files.
+\bRCS\b
+\bCVS\b
+,v$
+\B\.svn\b
+\B\.git\b
+\B\.gitignore\b
+
+# Avoid Makemaker generated and utility files.
+\bMakefile$
+\bblib
+\bMakeMaker-\d
+\bpm_to_blib$
+\bblibdirs$
+^MANIFEST\.SKIP$
+
+# Avoid Module::Build generated and utility files.
+\bBuild$
+\b_build
+
+# Avoid temp and backup files.
+~$
+\.tmp$
+\.old$
+\.bak$
+\#$
+\b\.#
+\.DS_Store$
+
+# No tarballs!
+\.gz$
+
+# Avoid spelling test.
+pod-spelling.t$

Added: Catalyst-View-TD/trunk/Makefile.PL
===================================================================
--- Catalyst-View-TD/trunk/Makefile.PL	                        (rev 0)
+++ Catalyst-View-TD/trunk/Makefile.PL	2009-10-09 06:19:26 UTC (rev 11510)
@@ -0,0 +1,25 @@
+use inc::Module::Install 0.87;
+
+if ( -e 'MANIFEST.SKIP' ) {
+    system( 'pod2text lib/Catalyst/View/TD.pm > README' );
+}
+
+perl_version '5.008001';
+
+name 'Catalyst-View-TD';
+all_from 'lib/Catalyst/View/TD.pm';
+
+requires 'Catalyst'          => '5.7';
+requires 'Template::Declare' => '0.41';
+requires 'File::Find'        => 0;
+# requires 'Class::Accessor'   => 0;
+# requires 'Template::Timer'   => 0;
+# requires 'Path::Class'       => 0;
+# requires 'MRO::Compat'       => 0;
+
+test_requires 'Test::More';
+
+auto_install;
+resources repository => 'http://dev.catalyst.perl.org/repos/Catalyst/trunk/Catalyst-View-TD/';
+
+WriteAll;

Added: Catalyst-View-TD/trunk/lib/Catalyst/Helper/View/TD.pm
===================================================================
--- Catalyst-View-TD/trunk/lib/Catalyst/Helper/View/TD.pm	                        (rev 0)
+++ Catalyst-View-TD/trunk/lib/Catalyst/Helper/View/TD.pm	2009-10-09 06:19:26 UTC (rev 11510)
@@ -0,0 +1,97 @@
+package Catalyst::Helper::View::TD;
+
+use strict;
+
+=head1 Name
+
+Catalyst::Helper::View::TD - Helper for TD Views
+
+=head1 Synopsis
+
+    myapp_create.pl view HTML TD
+
+=head1 Description
+
+Helper for TD Views.
+
+=head2 Methods
+
+=head3 mk_compclass
+
+=cut
+
+sub mk_compclass {
+    my ( $self, $helper ) = @_;
+    my $file = $helper->{file};
+    $helper->render_file( 'compclass', $file );
+}
+
+=head1 SEE ALSO
+
+L<Catalyst::View::TD>, L<Catalyst::Manual>, L<Catalyst::Test>,
+L<Catalyst::Request>, L<Catalyst::Response>, L<Catalyst::Helper>
+
+=head1 Author
+
+David E. Wheeler <david at justatheory.com>
+
+=head1 License
+
+This library is free software. You can redistribute it and/or modify it under
+the same terms as perl itself.
+
+=cut
+
+1;
+
+__DATA__
+
+__compclass__
+[% PERL %]
+(my $tclass = $stash->get('class')) =~ s/::View::/::TD::/;
+$stash->set(tclass => $tclass );
+[% END %]
+package [% class %];
+
+use strict;
+use warnings;
+
+use parent 'Catalyst::View::TD';
+
+# If roots is not specified, Catalyst::View::TD will automatically load all
+# modules below the [% class %]::* namespace. It's simplest to create
+# your template modules there. See the Template::Declare documentation for a
+# complete description of its init() parameters, all of which are supported
+# here.
+
+__PACKAGE__->config(
+    # dispatch_to     => [qw([% tclass %])],
+    # postprocessor   => sub { ... },
+    # around_template => sub { ... },
+);
+
+=head1 NAME
+
+[% class %] - TD View for [% app %]
+
+=head1 DESCRIPTION
+
+TD View for [% app %]. Templates are written in the
+[% tclass %] namespace.
+
+=head1 SEE ALSO
+
+L<[% app %]>
+
+=head1 AUTHOR
+
+[% author %]
+
+=head1 LICENSE
+
+This library is free software. You can redistribute it and/or modify it under
+the same terms as Perl itself.
+
+=cut
+
+1;

Added: Catalyst-View-TD/trunk/lib/Catalyst/View/TD.pm
===================================================================
--- Catalyst-View-TD/trunk/lib/Catalyst/View/TD.pm	                        (rev 0)
+++ Catalyst-View-TD/trunk/lib/Catalyst/View/TD.pm	2009-10-09 06:19:26 UTC (rev 11510)
@@ -0,0 +1,448 @@
+package Catalyst::View::TD;
+
+use strict;
+use warnings;
+
+use base qw/Catalyst::View/;
+
+our $VERSION = '0.01';
+
+__PACKAGE__->mk_accessors('init');
+
+=head1 Name
+
+Catalyst::View::TD - Catalyst Template::Declare View Class
+
+=head1 Synopsis
+
+Use the helper to create your view:
+
+    myapp_create.pl view HTML TD
+
+Configure in F<lib/MyApp.pm> (could be set from configfile instead):
+
+    MyApp->config(
+        name     => 'MyApp',
+        root     => MyApp->path_to('root'),
+        'View::TD' => {
+            dispatch_to     => ['MyApp::View::TD::Root'], # Default
+            preprocessor    => sub { ... },
+            around_template => sub { ... },
+        },
+    );
+
+Create a template in F<lib/MyApp/TD/HTML.pm>:
+
+    package TestApp::TD::HTML;
+
+    use strict;
+    use warnings;
+    use Template::Declare::Tags;
+
+    template hello => sub {
+        my ($self, $vars) = @_;
+        html {
+            head { title { "Hello, $vars->{user}" } };
+            body { h1    { "Hello, $vars->{user}" } };
+        };
+    };
+
+Render the view from MyApp::Controller::SomeController:
+
+    sub message : Global {
+        my ( $self, $c ) = @_;
+        $c->stash->{template} = 'hello';
+        $c->stash->{user}     = 'Slim Shady';
+        $c->forward( $c->view('TD') );
+    }
+
+=cut
+
+sub new {
+    my ( $class, $c, $args ) = @_;
+    my $config = {
+        %{ $class->config },
+        %{ $args },
+    };
+
+    if (my $roots = $config->{dispatch_to}) {
+        for my $root (@{ $roots }) {
+            eval "require $root" or die $@ || "$root did not return a true value";
+        }
+    } else {
+        $config->{dispatch_to} = _load_templates( $class );
+    }
+
+    $class->next::method( $c, { init => $config } );
+}
+
+sub _load_templates {
+    my $class = shift;
+
+    (my $root = $class) =~ s/::View::/::TD::/;
+
+    my $classes = [
+        Module::Pluggable::Object->new(
+            require     => 0,
+            search_path => $root,
+        )->plugins
+    ];
+
+    for my $mod ($root, $@{ $classes }) {
+        next unless $mod;
+        # Load it.
+        eval "require $mod" or die $@ || "$mod did not return a true value";
+
+        # Make the module a subclass of TD (required by TD)
+        unless ( $mod->isa('Template::Declare::Catalyst') ) {
+            no strict 'refs';
+            push @{ "$mod\::ISA" }, 'Template::Declare::Catalyst'
+        }
+
+        next if $mod eq $root;
+
+        # Mix it in.
+        (my $sub = $mod) =~ s/\Q$root\E:://;
+        my $path = join '/', map {
+            s{(?!^)([[:upper:]])+}{_$1}g; lc
+        } split /::/ => $sub;
+        $mod->mix($root, $path);
+    }
+    return [$root];
+}
+
+sub process {
+    my ( $self, $c ) = @_;
+
+    my $template = $c->stash->{template} || $c->action;
+
+    unless (defined $template) {
+        $c->log->debug('No template specified for rendering') if $c->debug;
+        return 0;
+    }
+
+    my $output = eval { $self->render($c, $template) };
+
+    if (my $error = $@) {
+        my $error = qq/Couldn't render template: "$error"/;
+        $c->log->error($error);
+        $c->error($error);
+        return 0;
+    }
+
+    unless ( $c->response->content_type ) {
+        $c->response->content_type('text/html; charset=utf-8');
+    }
+
+    $c->response->body($output);
+
+    return 1;
+}
+
+sub render {
+    my ($self, $c, $template, $args) = @_;
+
+    $c->log->debug(qq/Rendering template "$template"/) if $c && $c->debug;
+
+    my $vars = {
+        ref $args eq 'HASH' ? %{ $args || {} } : $c ? %{ $c->stash } : {},
+    };
+    Template::Declare->init( %{ $self->init } );
+    Template::Declare::Catalyst->context($c);
+    my $output = eval { Template::Declare->show($template, $vars) };
+    if (my $err = $@) {
+        return $err if ref $err;
+        die $err;
+    }
+    return $output;
+}
+
+package Template::Declare::Catalyst;
+
+use strict;
+use warnings;
+use lib '/Users/david/dev/perl/Template-Declare/mixmaster/lib';
+use base qw/Template::Declare/;
+
+__PACKAGE__->mk_classdata('context');
+
+*c = \&context;
+
+# XXX Not sure if this is the best way to do things.
+TAGS: {
+    use Template::Declare::Tags ();
+    no warnings 'redefine';
+    *Template::Declare::Tags::carp = sub { die \join '', @_ };
+}
+
+1;
+__END__
+
+=head1 Description
+
+This is the Catalyst view class for L<Template::Declare|Template::Declare>.
+Your application should defined a view class which is a subclass of this
+module. The easiest way to achieve this is using the F<myapp_create.pl> script
+(where F<myapp> should be replaced with whatever your application is called).
+This script is created as part of the Catalyst setup.
+
+    $ script/myapp_create.pl view HTML TD
+
+This creates a C<MyApp::View::HTML> module in the F<lib> directory (again,
+replacing C<MyApp> with the name of your application) which looks something
+like this:
+
+    package MyApp::View::HTML;
+
+    use strict;
+    use warnings;
+
+    use base 'Catalyst::View::TD';
+
+    __PACKAGE__->config->{DEBUG} = 'all';
+
+Now you can modify your action handlers in the main application and/or
+controllers to forward to your view class. You might choose to do this in the
+C<end()> method, for example, to automatically forward all actions to the TD
+view class.
+
+    # In MyApp or MyApp::Controller::SomeController
+
+    sub end : Private {
+        my( $self, $c ) = @_;
+        $c->forward( $c->view('HTML') );
+    }
+
+=head2 Configuration
+
+There are a three different ways to configure your view class. The first way
+is to call the C<config()> method in the view subclass. This happens when the
+module is first loaded.
+
+    package MyApp::View::TD;
+
+    use strict;
+    use base 'Catalyst::View::TD';
+
+    MyApp::View::TD->config({
+        dispatch_to     => [ 'MyApp::TD::HTML' ],
+        postprocessor   => sub { ... },
+        around_template => sub { ... },
+    });
+
+The second way is to define a C<new()> method in your view subclass. This
+performs the configuration when the view object is created, shortly after
+being loaded. Remember to delegate to the base class C<new()> method (via
+C<< $self->next::method() >> in the example below) after performing any
+configuration.
+
+    sub new {
+        my $self = shift;
+        $self->config({
+            dispatch_to     => [ 'MyApp::TD::HTML' ],
+            postprocessor   => sub { ... },
+            around_template => sub { ... },
+        });
+        return $self->next::method(@_);
+    }
+
+The final, and perhaps most direct way, is to define a class item in your main
+application configuration, again by calling the ubiquitous C<config()> method.
+The items in the class hash are added to those already defined by the above
+two methods. This happens in the base class C<new()> method (which is one
+reason why you must remember to call it via C<MRO::Compat> if you redefine the
+C<new()> method in a subclass).
+
+    package MyApp;
+
+    use strict;
+    use Catalyst;
+
+    MyApp->config({
+        name     => 'MyApp',
+        'View::HTML' => {
+            dispatch_to     => [ 'MyApp::TD::HTML' ],
+            postprocessor   => sub { ... },
+            around_template => sub { ... },
+        },
+    });
+
+Note that any configuration items defined by one of the earlier methods will
+be overwritten by items of the same name provided by the latter methods.
+
+=begin comment
+
+Implement this?
+
+=head2 Dynamic C<dispatch_to>
+
+Sometimes it is desirable to modify C<dispatch_to> for your templates at
+runtime.
+
+Additional paths can be added to the start of C<dispatch_to> via the stash as
+follows:
+
+    $c->stash->{additional_template_classes} = [
+        'MyApp::Other::Templates'
+    ];
+
+If you need to add template classes paths to the end of C<dispatch_to>, there
+is also a C<include_path()> accessor:
+
+    push( @{ $c->view('HTML')->dispatch_to }, 'My::Templates' );
+
+Note that if you use C<dispatch_to()> to add extra paths to C<dispatch_to>,
+you B<must> check for duplicate paths. Without such checking, the above code
+will add "My::Templates" to C<dispatch_to> for every request, leading to a
+memory leak.
+
+A safer approach is to use C<dispatch_to()> to overwrite the array of template
+classes rather than adding to it. This eliminates both the need to perform
+duplicate checking and the chance of a memory leak:
+
+    $c->view('HTML')->dispatch_to( ['My::Templates', 'Your::Templates'] );
+
+If you are calling C<render> directly then you can specify dynamic paths by
+having a C<additional_template_classes> key with a value of additonal
+directories to search. See L</"Capturing Template Output"> for an example of
+this.
+
+=end comment
+
+=head2 Rendering Views
+
+The Catlyst C<view()> method renders the template specified in the C<template>
+item in the stash.
+
+    sub message : Global {
+        my ( $self, $c ) = @_;
+        $c->stash->{template} = 'message';
+        $c->forward( $c->view('HTML') );
+    }
+
+If a stash item isn't defined, then it instead uses the stringification of the
+action dispatched to (as defined by C<< $c->action >>). In the above example,
+this would be C<message>.
+
+The items defined in the stash are passed to the the Template::Declare template
+as a hash reference. Thus, for this controller action:
+
+    sub default : Private {
+        my ( $self, $c ) = @_;
+        $c->stash->{template} = 'message';
+        $c->stash->{message}  = 'Hello World!';
+        $c->forward( $c->view('TD') );
+    }
+
+Your template can use access the C<message> key like so:
+
+    template message => sub {
+        my ($self, $args) = @_;
+        h1 { $args->{message} };
+    };
+
+Template classes are automatically subclasses of Template::Declare::Catalyst,
+which is itself a subclass of L<Template::Declare|Template::Declare>.
+Template::Declare::Catalyst provides a few extra accessors for use in your
+templates:
+
+=over
+
+=item C<context>
+
+A reference to the context object, C<$c>
+
+=item C<c>
+
+An alias for C<context()>
+
+=begin comment
+
+Add these?
+
+=item C<base>
+
+The URL base, from C<< $c->req->base >>.
+
+=item C<name>
+
+The application name, from C<< $c->config->{ name } >>.
+
+=end comment
+
+=back
+
+These can be accessed from the template like so:
+
+    template message => sub {
+        my ($self, $args) = @_;
+        p { "The message is $args->{message}" };
+        p { "The base is " . $self->base };
+        p { "The name is " . $self->name };
+    };
+
+The output generated by the template is stored in C<< $c->response->body >>.
+
+=head2 Capturing Template Output
+
+If you wish to use the output of a template for some purpose other than
+displaying in the response, e.g. for sending an email, use
+L<Catalyst::Plugin::Email|Catalyst::Plugin::Email> and the L<render> method:
+
+    sub send_email : Local {
+        my ($self, $c) = @_;
+
+        $c->email(
+            header => [
+                To      => 'me at localhost',
+                Subject => 'A TD Email',
+            ],
+            body => $c->view('TD')->render($c, 'email', {
+                additional_template_classes => [ 'My::EmailTemplates' ],
+                email_tmpl_param1 => 'foo'
+            }),
+        );
+        # Redirect or display a message
+    }
+
+=head2 Methods
+
+=head2 C<new>
+
+The constructor for the TD view. Sets up the template provider and reads the
+application config.
+
+=head2 C<process>
+
+Renders the template specified in C<< $c->stash->{template} >> or
+C<< $c->action >> (the private name of the matched action). Calls L<render()>
+to perform actual rendering. Output is stored in C<< $c->response->body >>.
+
+=head2 C<render>
+
+Renders the given template and returns output, or a L<Template::Exception>
+object upon error.
+
+The template variables are set to C<$args> if $args is a hashref, or
+C<< $c->stash >> otherwise.
+
+=head2 C<config>
+
+This method allows your view subclass to pass additional settings to the TD
+configuration hash, or to set the options as below:
+
+=head1 SEE ALSO
+
+L<Catalyst>, L<Catalyst::View::TT>, L<Catalyst::Helper::View::TD>,
+L<Catalyst::Helper::View::TDSite>, L<Template::Manual>
+
+=head1 Author
+
+David E. Wheeler <david at justatheory.com>
+
+=head1 Copyright
+
+This program is free software. You can redistribute it and/or modify it under
+the same terms as Perl itself.
+
+=cut

Added: Catalyst-View-TD/trunk/t/01use.t
===================================================================
--- Catalyst-View-TD/trunk/t/01use.t	                        (rev 0)
+++ Catalyst-View-TD/trunk/t/01use.t	2009-10-09 06:19:26 UTC (rev 11510)
@@ -0,0 +1,5 @@
+use strict;
+use Test::More tests => 2;
+
+BEGIN { use_ok('Catalyst::View::TD') }
+BEGIN { use_ok('Catalyst::Helper::View::TD') }

Added: Catalyst-View-TD/trunk/t/02pod.t
===================================================================
--- Catalyst-View-TD/trunk/t/02pod.t	                        (rev 0)
+++ Catalyst-View-TD/trunk/t/02pod.t	2009-10-09 06:19:26 UTC (rev 11510)
@@ -0,0 +1,6 @@
+use Test::More;
+
+eval "use Test::Pod 1.14";
+plan skip_all => 'Test::Pod 1.14 required' if $@;
+
+all_pod_files_ok();

Added: Catalyst-View-TD/trunk/t/03podcoverage.t
===================================================================
--- Catalyst-View-TD/trunk/t/03podcoverage.t	                        (rev 0)
+++ Catalyst-View-TD/trunk/t/03podcoverage.t	2009-10-09 06:19:26 UTC (rev 11510)
@@ -0,0 +1,6 @@
+use Test::More;
+
+eval "use Test::Pod::Coverage 1.04";
+plan skip_all => 'Test::Pod::Coverage 1.04 required' if $@;
+
+all_pod_coverage_ok();

Added: Catalyst-View-TD/trunk/t/04pkgconfig.t
===================================================================
--- Catalyst-View-TD/trunk/t/04pkgconfig.t	                        (rev 0)
+++ Catalyst-View-TD/trunk/t/04pkgconfig.t	2009-10-09 06:19:26 UTC (rev 11510)
@@ -0,0 +1,21 @@
+use strict;
+use warnings;
+use Test::More tests => 7;
+
+use FindBin;
+use lib "$FindBin::Bin/lib";
+
+use_ok('Catalyst::Test', 'TestApp');
+
+my $view = 'Pkgconfig';
+
+my $response;
+ok(($response = request("/test?view=$view"))->is_success, 'request ok');
+is($response->content, TestApp->config->{default_message}, 'default message ok');
+
+my $message = scalar localtime;
+ok(($response = request("/test?view=$view&message=$message"))->is_success, 'request with message ok');
+is($response->content,  $message, 'message ok');
+
+ok(($response = request("/test?view=$view&message=override"))->is_success, 'request with override message ok');
+is($response->content,  'Shoved in by around_template', 'override message ok');

Added: Catalyst-View-TD/trunk/t/05appconfig.t
===================================================================
--- Catalyst-View-TD/trunk/t/05appconfig.t	                        (rev 0)
+++ Catalyst-View-TD/trunk/t/05appconfig.t	2009-10-09 06:19:26 UTC (rev 11510)
@@ -0,0 +1,18 @@
+use strict;
+use warnings;
+use Test::More tests => 5;
+
+use FindBin;
+use lib "$FindBin::Bin/lib";
+
+use_ok('Catalyst::Test', 'TestApp');
+
+my $view = 'Appconfig';
+
+my $response;
+ok(($response = request("/test?view=$view"))->is_success, 'request ok');
+is($response->content, TestApp->config->{default_message}, 'message ok');
+
+my $message = scalar localtime;
+ok(($response = request("/test?view=$view&message=$message"))->is_success, 'request with message ok');
+is($response->content, $message, 'message ok');

Added: Catalyst-View-TD/trunk/t/06includepath.t
===================================================================
--- Catalyst-View-TD/trunk/t/06includepath.t	                        (rev 0)
+++ Catalyst-View-TD/trunk/t/06includepath.t	2009-10-09 06:19:26 UTC (rev 11510)
@@ -0,0 +1,30 @@
+use strict;
+use warnings;
+use Test::More skip_all => 'Not sure we will need this feature with TD';
+
+use Test::More tests => 10;
+
+use FindBin;
+use lib "$FindBin::Bin/lib";
+
+use_ok('Catalyst::Test', 'TestApp');
+my $response;
+
+my $inital_dispatch_to = [ @{ TestApp->view('Appconfig')->dispatch_to } ];
+
+ok(($response = request("/test_includepath?view=Appconfig&template=testpath&additionalpath=test_dispatch_to"))->is_success, 'additional_template_path request');
+is($response->content, TestApp->config->{default_message}, 'additional_template_path message');
+
+is_deeply($inital_dispatch_to,
+    TestApp->view('Appconfig')->dispatch_to,
+    'Include path is unchanged');
+
+ok(($response = request("/test_includepath?view=Includepath&template=testpath"))->is_success, 'scalar include path from config request');
+is($response->content, TestApp->config->{default_message}, 'scalar include path with delimiter from config message');
+
+ok(($response = request("/test_includepath?view=Includepath2&template=testpath"))->is_success, 'object ref (that stringifys to the path) include path from config request');
+is($response->content, TestApp->config->{default_message}, 'object ref (that stringifys to the path) include path from config message');
+
+ok(($response = request("/test_includepath?view=Includepath3&template=testpath&addpath=test_dispatch_to"))->is_success, 'array ref include path from config not replaced by another array request');
+is($response->content, TestApp->config->{default_message}, 'array ref include path from config not replaced by another array message');
+

Added: Catalyst-View-TD/trunk/t/07render.t
===================================================================
--- Catalyst-View-TD/trunk/t/07render.t	                        (rev 0)
+++ Catalyst-View-TD/trunk/t/07render.t	2009-10-09 06:19:26 UTC (rev 11510)
@@ -0,0 +1,22 @@
+use strict;
+use warnings;
+use Test::More tests => 5;
+
+use FindBin;
+use lib "$FindBin::Bin/lib";
+
+use_ok('Catalyst::Test', 'TestApp');
+
+my $response;
+ok(($response = request("/test_render?template=specified_template&param=parameterized"))->is_success, 'request ok');
+is($response->content, "I should be a parameterized test in @{[TestApp->config->{name}]}", 'message ok');
+
+# TD does not support template text passed as a code ref.
+# my $message = 'Dynamic message';
+# ok(($response = request("/test_msg?msg=$message"))->is_success, 'request ok');
+# is($response->content, "$message", 'message ok');
+
+$response = request("/test_render?template=non_existant_template");
+
+is (403, $response->code, 'request returned error');
+is($response->content, q{The template 'non_existant_template' could not be found (it might be private)}, 'Error from non-existant-template');

Added: Catalyst-View-TD/trunk/t/08cycle.t
===================================================================
--- Catalyst-View-TD/trunk/t/08cycle.t	                        (rev 0)
+++ Catalyst-View-TD/trunk/t/08cycle.t	2009-10-09 06:19:26 UTC (rev 11510)
@@ -0,0 +1,31 @@
+use strict;
+use warnings;
+use Test::More;
+
+use FindBin;
+use lib "$FindBin::Bin/lib";
+
+plan tests => 3;
+
+use_ok('Catalyst::View::TD');
+use_ok('Catalyst::Test', 'TestApp');
+
+my $copy;
+{
+    my $view = Catalyst::View::TD->new(
+        "TestApp",
+        { dispatch_to => ['TestApp::TD::Appconfig'] },
+    );
+
+    # Can't Test::Memory::Cycle test since it doesn't detect
+    #  [ sub { $copy->paths } ]
+    # as a cycle, but the above does prevent it getting garbage collected.
+    #
+    # memory_cycle_ok($view, 'No cycles in View');
+
+    $copy = $view;
+    Scalar::Util::weaken($copy);
+}
+
+ok(!defined $copy, 'Copy went out of scope');
+

Added: Catalyst-View-TD/trunk/t/11norequest.t
===================================================================
--- Catalyst-View-TD/trunk/t/11norequest.t	                        (rev 0)
+++ Catalyst-View-TD/trunk/t/11norequest.t	2009-10-09 06:19:26 UTC (rev 11510)
@@ -0,0 +1,12 @@
+use strict;
+use warnings;
+use Test::More tests => 3;
+
+use FindBin;
+use lib "$FindBin::Bin/lib";
+
+BEGIN { use_ok 'TestApp' or die }
+
+ok my $td = TestApp->view('Appconfig'), 'Get Appconfig view object';
+is $td->render(undef, 'test', { message => 'hello' }), 'hello',
+    'render() should return the template output';

Added: Catalyst-View-TD/trunk/t/lib/TestApp/TD/Appconfig.pm
===================================================================
--- Catalyst-View-TD/trunk/t/lib/TestApp/TD/Appconfig.pm	                        (rev 0)
+++ Catalyst-View-TD/trunk/t/lib/TestApp/TD/Appconfig.pm	2009-10-09 06:19:26 UTC (rev 11510)
@@ -0,0 +1,17 @@
+package TestApp::TD::Appconfig;
+
+use strict;
+use warnings;
+use Template::Declare::Tags;
+
+template test => sub {
+    my ($self, $args) = @_;
+    outs $args->{message};
+};
+
+template specified_template => sub {
+    my ($self, $args) = @_;
+    outs "I should be a $args->{param} test in ", $self->c->config->{name};
+};
+
+1;

Added: Catalyst-View-TD/trunk/t/lib/TestApp/Template/Pkgconfig.pm
===================================================================
--- Catalyst-View-TD/trunk/t/lib/TestApp/Template/Pkgconfig.pm	                        (rev 0)
+++ Catalyst-View-TD/trunk/t/lib/TestApp/Template/Pkgconfig.pm	2009-10-09 06:19:26 UTC (rev 11510)
@@ -0,0 +1,12 @@
+package TestApp::Template::Pkgconfig;
+
+use strict;
+use Template::Declare::Tags;
+use base 'Template::Declare::Catalyst';
+
+template test => sub {
+    my ($self, $msg, $args) = @_;
+    outs $args->{message} eq 'override' ? $msg : $args->{message};
+};
+
+1;

Added: Catalyst-View-TD/trunk/t/lib/TestApp/View/Appconfig.pm
===================================================================
--- Catalyst-View-TD/trunk/t/lib/TestApp/View/Appconfig.pm	                        (rev 0)
+++ Catalyst-View-TD/trunk/t/lib/TestApp/View/Appconfig.pm	2009-10-09 06:19:26 UTC (rev 11510)
@@ -0,0 +1,6 @@
+package TestApp::View::Appconfig;
+
+use strict;
+use base 'Catalyst::View::TD';
+
+1;


Property changes on: Catalyst-View-TD/trunk/t/lib/TestApp/View/Appconfig.pm
___________________________________________________________________
Name: svn:executable
   + *

Added: Catalyst-View-TD/trunk/t/lib/TestApp/View/Pkgconfig.pm
===================================================================
--- Catalyst-View-TD/trunk/t/lib/TestApp/View/Pkgconfig.pm	                        (rev 0)
+++ Catalyst-View-TD/trunk/t/lib/TestApp/View/Pkgconfig.pm	2009-10-09 06:19:26 UTC (rev 11510)
@@ -0,0 +1,21 @@
+package TestApp::View::Pkgconfig;
+
+use strict;
+use base 'Catalyst::View::TD';
+
+__PACKAGE__->config(
+    dispatch_to   => [qw(TestApp::Template::Pkgconfig)],
+    postprocessor => sub {
+        local $_ = shift;
+        s/^\s+//msg;
+        s/\s+$//msg;
+        $_;
+    },
+    around_template => sub {
+        my ($orig, $path, $args, $code) = @_;
+        unshift @{ $args }, 'Shoved in by around_template';
+        $orig->();
+    },
+);
+
+1;


Property changes on: Catalyst-View-TD/trunk/t/lib/TestApp/View/Pkgconfig.pm
___________________________________________________________________
Name: svn:executable
   + *

Added: Catalyst-View-TD/trunk/t/lib/TestApp.pm
===================================================================
--- Catalyst-View-TD/trunk/t/lib/TestApp.pm	                        (rev 0)
+++ Catalyst-View-TD/trunk/t/lib/TestApp.pm	2009-10-09 06:19:26 UTC (rev 11510)
@@ -0,0 +1,90 @@
+package TestApp;
+
+use strict;
+use warnings;
+
+use Catalyst; # qw/-Debug/;
+use Path::Class;
+
+our $VERSION = '0.01';
+
+__PACKAGE__->config(
+    name                  => 'TestApp',
+    default_message       => 'hi',
+    default_view          => 'Appconfig',
+    'View::TD::Appconfig' => {
+        postprocessor => sub { $_[0] =~ s/\s+$//; $_[0] },
+    },
+);
+
+__PACKAGE__->setup;
+
+1;
+
+# package TestApp::Controller::Root;
+# use base 'Catalyst::Controller';
+# BEGIN { $INC{'TestApp/Controller/Root.pm'} = __FILE__ }
+
+sub default : Private {
+    my ($self, $c) = @_;
+
+    $c->response->redirect($c->uri_for('test'));
+}
+
+sub test : Local {
+    my ($self, $c) = @_;
+    $c->stash->{message} = $c->request->param('message') || $c->config->{default_message};
+}
+
+sub test_includepath : Local {
+    my ($self, $c) = @_;
+    $c->stash->{message} = ($c->request->param('message') || $c->config->{default_message});
+    $c->stash->{template} = $c->request->param('template');
+    if ( $c->request->param('additionalpath') ){
+        my $additionalpath = Path::Class::dir($c->config->{root}, $c->request->param('additionalpath'));
+        $c->stash->{additional_template_paths} = ["$additionalpath"];
+    }
+    if ( $c->request->param('addpath') ){
+        my $additionalpath = Path::Class::dir($c->config->{root}, $c->request->param('addpath'));
+        my $view = 'TestApp::View::' . ($c->request->param('view') || $c->config->{default_view});
+        no strict "refs";
+        push @{$view . '::include_path'}, "$additionalpath";
+        use strict;
+    }
+}
+
+sub test_render : Local {
+    my ($self, $c) = @_;
+
+    my $out = $c->stash->{message} = $c->view('Appconfig')->render(
+        $c, $c->req->param('template'), {param => $c->req->param('param') || ''}
+    );
+    if (ref $out) {
+        $c->response->body($$out);
+        $c->response->status(403);
+    } else {
+        $c->stash->{template} = 'test';
+    }
+
+}
+
+sub test_msg : Local {
+    my ($self, $c) = @_;
+    my $tmpl = $c->req->param('msg');
+    # Test commented-out in 07render.t: TD does not support template text as a
+    # scalar ref, because templates are not text, they're code.
+    $c->stash->{message} = $c->view('AppConfig')->render($c, \$tmpl);
+    $c->stash->{template} = 'test';
+}
+
+sub end : Private {
+    my ($self, $c) = @_;
+
+    return 1 if $c->response->status =~ /^3\d\d$/;
+    return 1 if $c->response->body;
+
+    my $view = 'View::' . ($c->request->param('view') || $c->config->{default_view});
+    $c->forward($view);
+}
+
+1;


Property changes on: Catalyst-View-TD/trunk/t/lib/TestApp.pm
___________________________________________________________________
Name: svn:executable
   + *




More information about the Catalyst-commits mailing list