RT 4.0.22
[freeside.git] / rt / t / api / template-parsing.t
1 use strict;
2 use warnings;
3 use RT;
4 use RT::Test tests => 266;
5 use Test::Warn;
6
7 my $queue = RT::Queue->new(RT->SystemUser);
8 $queue->Load("General");
9
10 my $ticket_cf = RT::CustomField->new(RT->SystemUser);
11 $ticket_cf->Create(
12     Name        => 'Department',
13     Queue       => '0',
14     Type        => 'FreeformSingle',
15 );
16
17 my $txn_cf = RT::CustomField->new(RT->SystemUser);
18 $txn_cf->Create(
19     Name        => 'Category',
20     LookupType  => RT::Transaction->CustomFieldLookupType,
21     Type        => 'FreeformSingle',
22 );
23 $txn_cf->AddToObject($queue);
24
25 my $ticket = RT::Ticket->new(RT->SystemUser);
26 my ($id, $msg) = $ticket->Create(
27     Subject   => "template testing",
28     Queue     => "General",
29     Owner     => 'root@localhost',
30     Requestor => ["dom\@example.com"],
31     "CustomField-" . $txn_cf->id => "Special",
32 );
33 ok($id, "Created ticket: $msg");
34 my $txn = $ticket->Transactions->First;
35
36 $ticket->AddCustomFieldValue(
37     Field => 'Department',
38     Value => 'Coolio',
39 );
40
41 TemplateTest(
42     Content      => "\ntest",
43     PerlOutput   => "test",
44     SimpleOutput => "test",
45 );
46
47 TemplateTest(
48     Content      => "\ntest { 5 * 5 }",
49     PerlOutput   => "test 25",
50     SimpleOutput => "test { 5 * 5 }",
51 );
52
53 TemplateTest(
54     Content      => "\ntest { \$Requestor }",
55     PerlOutput   => "test dom\@example.com",
56     SimpleOutput => "test dom\@example.com",
57 );
58
59 TemplateTest(
60     Content      => "\ntest { \$TicketSubject }",
61     PerlOutput   => "test ",
62     SimpleOutput => "test template testing",
63 );
64
65 SimpleTemplateTest(
66     Content => "\ntest { \$TicketQueueId }",
67     Output  => "test 1",
68 );
69
70 SimpleTemplateTest(
71     Content => "\ntest { \$TicketQueueName }",
72     Output  => "test General",
73 );
74
75 SimpleTemplateTest(
76     Content => "\ntest { \$TicketOwnerId }",
77     Output  => "test 12",
78 );
79
80 SimpleTemplateTest(
81     Content => "\ntest { \$TicketOwnerName }",
82     Output  => "test root",
83 );
84
85 SimpleTemplateTest(
86     Content => "\ntest { \$TicketOwnerEmailAddress }",
87     Output  => "test root\@localhost",
88 );
89
90 SimpleTemplateTest(
91     Content => "\ntest { \$TicketStatus }",
92     Output  => "test new",
93 );
94
95 SimpleTemplateTest(
96     Content => "\ntest #{ \$TicketId }",
97     Output  => "test #" . $ticket->id,
98 );
99
100 SimpleTemplateTest(
101     Content => "\ntest { \$TicketCFDepartment }",
102     Output  => "test Coolio",
103 );
104
105 SimpleTemplateTest(
106     Content => "\ntest #{ \$TransactionId }",
107     Output  => "test #" . $txn->id,
108 );
109
110 SimpleTemplateTest(
111     Content => "\ntest { \$TransactionType }",
112     Output  => "test Create",
113 );
114
115 SimpleTemplateTest(
116     Content => "\ntest { \$TransactionCFCategory }",
117     Output  => "test Special",
118 );
119
120 SimpleTemplateTest(
121     Content => "\ntest { \$TicketDelete }",
122     Output  => "test { \$TicketDelete }",
123 );
124
125 SimpleTemplateTest(
126     Content => "\ntest { \$Nonexistent }",
127     Output  => "test { \$Nonexistent }",
128 );
129
130 warning_like {
131     TemplateTest(
132         Content      => "\ntest { \$Ticket->Nonexistent }",
133         PerlOutput   => undef,
134         SimpleOutput => "test { \$Ticket->Nonexistent }",
135     );
136 } qr/RT::Ticket::Nonexistent Unimplemented/;
137
138 warning_like {
139     TemplateTest(
140         Content      => "\ntest { \$Nonexistent->Nonexistent }",
141         PerlOutput   => undef,
142         SimpleOutput => "test { \$Nonexistent->Nonexistent }",
143     );
144 } qr/Can't call method "Nonexistent" on an undefined value/;
145
146 TemplateTest(
147     Content      => "\ntest { \$Ticket->OwnerObj->Name }",
148     PerlOutput   => "test root",
149     SimpleOutput => "test { \$Ticket->OwnerObj->Name }",
150 );
151
152 warning_like {
153     TemplateTest(
154         Content      => "\ntest { *!( }",
155         SyntaxError  => 1,
156         PerlOutput   => undef,
157         SimpleOutput => "test { *!( }",
158     );
159 } qr/Template parsing error: syntax error/;
160
161 TemplateTest(
162     Content      => "\ntest { \$rtname ",
163     SyntaxError  => 1,
164     PerlOutput   => undef,
165     SimpleOutput => undef,
166 );
167
168 is($ticket->Status, 'new', "test setup");
169 SimpleTemplateTest(
170     Content => "\ntest { \$Ticket->SetStatus('resolved') }",
171     Output  => "test { \$Ticket->SetStatus('resolved') }",
172 );
173 is($ticket->Status, 'new', "simple templates can't call ->SetStatus");
174
175 note "test arguments passing";
176 {
177     PerlTemplateTest(
178         Content => "\ntest { \$Nonexistent }",
179         Output  => "test ",
180     );
181     PerlTemplateTest(
182         Content   => "\ntest { \$Nonexistent }",
183         Arguments => { Nonexistent => 'foo' },
184         Output    => "test foo",
185     );
186
187     PerlTemplateTest(
188         Content   => "\n".'array: { join ", ", @array }',
189         Arguments => { array => [qw(foo bar)] },
190         Output    => "array: foo, bar",
191     );
192     PerlTemplateTest(
193         Content   => "\n".'hash: { join ", ", map "$_ => $hash{$_}", sort keys %hash }',
194         Arguments => { hash => {1 => 2, a => 'b'} },
195         Output    => "hash: 1 => 2, a => b",
196     );
197     PerlTemplateTest(
198         Content   => "\n".'code: { code() }',
199         Arguments => { code => sub { "baz" } },
200         Output    => "code: baz",
201     );
202 }
203
204 # Make sure changing the template's type works
205 {
206     my $template = RT::Template->new(RT->SystemUser);
207     $template->Create(
208         Name    => "type chameleon",
209         Type    => "Perl",
210         Content => "\ntest { 10 * 7 }",
211     );
212     ok($id = $template->id, "Created template");
213     $template->Parse;
214     is($template->MIMEObj->stringify_body, "test 70", "Perl output");
215
216     $template = RT::Template->new(RT->SystemUser);
217     $template->Load($id);
218     is($template->Name, "type chameleon");
219
220     $template->SetType('Simple');
221     $template->Parse;
222     is($template->MIMEObj->stringify_body, "test { 10 * 7 }", "Simple output");
223
224     $template = RT::Template->new(RT->SystemUser);
225     $template->Load($id);
226     is($template->Name, "type chameleon");
227
228     $template->SetType('Perl');
229     $template->Parse;
230     is($template->MIMEObj->stringify_body, "test 70", "Perl output");
231 }
232
233 undef $ticket;
234
235 my $counter = 0;
236 sub IndividualTemplateTest {
237     local $Test::Builder::Level = $Test::Builder::Level + 1;
238
239     my %args = (
240         Name => "Test-" . ++$counter,
241         Type => "Perl",
242         @_,
243     );
244
245     my $t = RT::Template->new(RT->SystemUser);
246     $t->Create(
247         Name    => $args{Name},
248         Type    => $args{Type},
249         Content => $args{Content},
250     );
251
252     ok($t->id, "Created $args{Type} template");
253     is($t->Name, $args{Name}, "$args{Type} template name");
254     is($t->Content, $args{Content}, "$args{Type} content");
255     is($t->Type, $args{Type}, "template type");
256
257     # this should never blow up!
258     my ($ok, $msg) = $t->CompileCheck;
259
260     # we don't need to syntax check simple templates since if you mess them up
261     # it's safe to just use the input directly as the template's output
262     if ($args{SyntaxError} && $args{Type} eq 'Perl') {
263         ok(!$ok, "got a syntax error");
264     }
265     else {
266         ok($ok, $msg);
267     }
268
269     ($ok, $msg) = $t->Parse(
270         $args{'Arguments'}
271             ? ( %{ $args{'Arguments'} } )
272             : (TicketObj => $ticket, TransactionObj => $txn )
273         ,
274     );
275     if (defined $args{Output}) {
276         ok($ok, $msg);
277         is($t->MIMEObj->stringify_body, $args{Output}, "$args{Type} template's output");
278     }
279     else {
280         ok(!$ok, "expected a failure");
281     }
282 }
283
284 sub TemplateTest {
285     local $Test::Builder::Level = $Test::Builder::Level + 1;
286     my %args = @_;
287
288     for my $type ('Perl', 'Simple') {
289         IndividualTemplateTest(
290             %args,
291             Type   => $type,
292             Output => $args{$type . 'Output'},
293         );
294     }
295 }
296
297 sub SimpleTemplateTest {
298     local $Test::Builder::Level = $Test::Builder::Level + 1;
299     IndividualTemplateTest( @_, Type => 'Simple' );
300 }
301
302 sub PerlTemplateTest {
303     local $Test::Builder::Level = $Test::Builder::Level + 1;
304     IndividualTemplateTest( @_, Type => 'Perl' );
305 }
306