RT 4.0.22
[freeside.git] / rt / t / api / template-parsing.t
diff --git a/rt/t/api/template-parsing.t b/rt/t/api/template-parsing.t
new file mode 100644 (file)
index 0000000..455b84d
--- /dev/null
@@ -0,0 +1,306 @@
+use strict;
+use warnings;
+use RT;
+use RT::Test tests => 266;
+use Test::Warn;
+
+my $queue = RT::Queue->new(RT->SystemUser);
+$queue->Load("General");
+
+my $ticket_cf = RT::CustomField->new(RT->SystemUser);
+$ticket_cf->Create(
+    Name        => 'Department',
+    Queue       => '0',
+    Type        => 'FreeformSingle',
+);
+
+my $txn_cf = RT::CustomField->new(RT->SystemUser);
+$txn_cf->Create(
+    Name        => 'Category',
+    LookupType  => RT::Transaction->CustomFieldLookupType,
+    Type        => 'FreeformSingle',
+);
+$txn_cf->AddToObject($queue);
+
+my $ticket = RT::Ticket->new(RT->SystemUser);
+my ($id, $msg) = $ticket->Create(
+    Subject   => "template testing",
+    Queue     => "General",
+    Owner     => 'root@localhost',
+    Requestor => ["dom\@example.com"],
+    "CustomField-" . $txn_cf->id => "Special",
+);
+ok($id, "Created ticket: $msg");
+my $txn = $ticket->Transactions->First;
+
+$ticket->AddCustomFieldValue(
+    Field => 'Department',
+    Value => 'Coolio',
+);
+
+TemplateTest(
+    Content      => "\ntest",
+    PerlOutput   => "test",
+    SimpleOutput => "test",
+);
+
+TemplateTest(
+    Content      => "\ntest { 5 * 5 }",
+    PerlOutput   => "test 25",
+    SimpleOutput => "test { 5 * 5 }",
+);
+
+TemplateTest(
+    Content      => "\ntest { \$Requestor }",
+    PerlOutput   => "test dom\@example.com",
+    SimpleOutput => "test dom\@example.com",
+);
+
+TemplateTest(
+    Content      => "\ntest { \$TicketSubject }",
+    PerlOutput   => "test ",
+    SimpleOutput => "test template testing",
+);
+
+SimpleTemplateTest(
+    Content => "\ntest { \$TicketQueueId }",
+    Output  => "test 1",
+);
+
+SimpleTemplateTest(
+    Content => "\ntest { \$TicketQueueName }",
+    Output  => "test General",
+);
+
+SimpleTemplateTest(
+    Content => "\ntest { \$TicketOwnerId }",
+    Output  => "test 12",
+);
+
+SimpleTemplateTest(
+    Content => "\ntest { \$TicketOwnerName }",
+    Output  => "test root",
+);
+
+SimpleTemplateTest(
+    Content => "\ntest { \$TicketOwnerEmailAddress }",
+    Output  => "test root\@localhost",
+);
+
+SimpleTemplateTest(
+    Content => "\ntest { \$TicketStatus }",
+    Output  => "test new",
+);
+
+SimpleTemplateTest(
+    Content => "\ntest #{ \$TicketId }",
+    Output  => "test #" . $ticket->id,
+);
+
+SimpleTemplateTest(
+    Content => "\ntest { \$TicketCFDepartment }",
+    Output  => "test Coolio",
+);
+
+SimpleTemplateTest(
+    Content => "\ntest #{ \$TransactionId }",
+    Output  => "test #" . $txn->id,
+);
+
+SimpleTemplateTest(
+    Content => "\ntest { \$TransactionType }",
+    Output  => "test Create",
+);
+
+SimpleTemplateTest(
+    Content => "\ntest { \$TransactionCFCategory }",
+    Output  => "test Special",
+);
+
+SimpleTemplateTest(
+    Content => "\ntest { \$TicketDelete }",
+    Output  => "test { \$TicketDelete }",
+);
+
+SimpleTemplateTest(
+    Content => "\ntest { \$Nonexistent }",
+    Output  => "test { \$Nonexistent }",
+);
+
+warning_like {
+    TemplateTest(
+        Content      => "\ntest { \$Ticket->Nonexistent }",
+        PerlOutput   => undef,
+        SimpleOutput => "test { \$Ticket->Nonexistent }",
+    );
+} qr/RT::Ticket::Nonexistent Unimplemented/;
+
+warning_like {
+    TemplateTest(
+        Content      => "\ntest { \$Nonexistent->Nonexistent }",
+        PerlOutput   => undef,
+        SimpleOutput => "test { \$Nonexistent->Nonexistent }",
+    );
+} qr/Can't call method "Nonexistent" on an undefined value/;
+
+TemplateTest(
+    Content      => "\ntest { \$Ticket->OwnerObj->Name }",
+    PerlOutput   => "test root",
+    SimpleOutput => "test { \$Ticket->OwnerObj->Name }",
+);
+
+warning_like {
+    TemplateTest(
+        Content      => "\ntest { *!( }",
+        SyntaxError  => 1,
+        PerlOutput   => undef,
+        SimpleOutput => "test { *!( }",
+    );
+} qr/Template parsing error: syntax error/;
+
+TemplateTest(
+    Content      => "\ntest { \$rtname ",
+    SyntaxError  => 1,
+    PerlOutput   => undef,
+    SimpleOutput => undef,
+);
+
+is($ticket->Status, 'new', "test setup");
+SimpleTemplateTest(
+    Content => "\ntest { \$Ticket->SetStatus('resolved') }",
+    Output  => "test { \$Ticket->SetStatus('resolved') }",
+);
+is($ticket->Status, 'new', "simple templates can't call ->SetStatus");
+
+note "test arguments passing";
+{
+    PerlTemplateTest(
+        Content => "\ntest { \$Nonexistent }",
+        Output  => "test ",
+    );
+    PerlTemplateTest(
+        Content   => "\ntest { \$Nonexistent }",
+        Arguments => { Nonexistent => 'foo' },
+        Output    => "test foo",
+    );
+
+    PerlTemplateTest(
+        Content   => "\n".'array: { join ", ", @array }',
+        Arguments => { array => [qw(foo bar)] },
+        Output    => "array: foo, bar",
+    );
+    PerlTemplateTest(
+        Content   => "\n".'hash: { join ", ", map "$_ => $hash{$_}", sort keys %hash }',
+        Arguments => { hash => {1 => 2, a => 'b'} },
+        Output    => "hash: 1 => 2, a => b",
+    );
+    PerlTemplateTest(
+        Content   => "\n".'code: { code() }',
+        Arguments => { code => sub { "baz" } },
+        Output    => "code: baz",
+    );
+}
+
+# Make sure changing the template's type works
+{
+    my $template = RT::Template->new(RT->SystemUser);
+    $template->Create(
+        Name    => "type chameleon",
+        Type    => "Perl",
+        Content => "\ntest { 10 * 7 }",
+    );
+    ok($id = $template->id, "Created template");
+    $template->Parse;
+    is($template->MIMEObj->stringify_body, "test 70", "Perl output");
+
+    $template = RT::Template->new(RT->SystemUser);
+    $template->Load($id);
+    is($template->Name, "type chameleon");
+
+    $template->SetType('Simple');
+    $template->Parse;
+    is($template->MIMEObj->stringify_body, "test { 10 * 7 }", "Simple output");
+
+    $template = RT::Template->new(RT->SystemUser);
+    $template->Load($id);
+    is($template->Name, "type chameleon");
+
+    $template->SetType('Perl');
+    $template->Parse;
+    is($template->MIMEObj->stringify_body, "test 70", "Perl output");
+}
+
+undef $ticket;
+
+my $counter = 0;
+sub IndividualTemplateTest {
+    local $Test::Builder::Level = $Test::Builder::Level + 1;
+
+    my %args = (
+        Name => "Test-" . ++$counter,
+        Type => "Perl",
+        @_,
+    );
+
+    my $t = RT::Template->new(RT->SystemUser);
+    $t->Create(
+        Name    => $args{Name},
+        Type    => $args{Type},
+        Content => $args{Content},
+    );
+
+    ok($t->id, "Created $args{Type} template");
+    is($t->Name, $args{Name}, "$args{Type} template name");
+    is($t->Content, $args{Content}, "$args{Type} content");
+    is($t->Type, $args{Type}, "template type");
+
+    # this should never blow up!
+    my ($ok, $msg) = $t->CompileCheck;
+
+    # we don't need to syntax check simple templates since if you mess them up
+    # it's safe to just use the input directly as the template's output
+    if ($args{SyntaxError} && $args{Type} eq 'Perl') {
+        ok(!$ok, "got a syntax error");
+    }
+    else {
+        ok($ok, $msg);
+    }
+
+    ($ok, $msg) = $t->Parse(
+        $args{'Arguments'}
+            ? ( %{ $args{'Arguments'} } )
+            : (TicketObj => $ticket, TransactionObj => $txn )
+        ,
+    );
+    if (defined $args{Output}) {
+        ok($ok, $msg);
+        is($t->MIMEObj->stringify_body, $args{Output}, "$args{Type} template's output");
+    }
+    else {
+        ok(!$ok, "expected a failure");
+    }
+}
+
+sub TemplateTest {
+    local $Test::Builder::Level = $Test::Builder::Level + 1;
+    my %args = @_;
+
+    for my $type ('Perl', 'Simple') {
+        IndividualTemplateTest(
+            %args,
+            Type   => $type,
+            Output => $args{$type . 'Output'},
+        );
+    }
+}
+
+sub SimpleTemplateTest {
+    local $Test::Builder::Level = $Test::Builder::Level + 1;
+    IndividualTemplateTest( @_, Type => 'Simple' );
+}
+
+sub PerlTemplateTest {
+    local $Test::Builder::Level = $Test::Builder::Level + 1;
+    IndividualTemplateTest( @_, Type => 'Perl' );
+}
+