- #!/usr/bin/perl
- use strict;
- use warnings;
- # Absolute directory name required to not trip up Template::Latex
- $ENV{TMPDIR} = "$ENV{PWD}/t/var";
- use Test::More 'no_plan';
- use Test::Trap qw(trap $trap);
- use Test::Exception;
- use Error qw(:try :warndie);
- use LedgerSMB::AM;
- use LedgerSMB::Form;
- use LedgerSMB::Sysconfig;
- use LedgerSMB::Locale;
- use LedgerSMB::Template;
- use LedgerSMB::Template::Elements;
- use LedgerSMB::Template::CSV;
- use LedgerSMB::Template::HTML;
- use LedgerSMB::Template::LaTeX;
- use LedgerSMB::Template::TXT;
- $LedgerSMB::Sysconfig::tempdir = 't/var';
- my @r;
- my $temp;
- my $form;
- my $myconfig;
- my $template;
- my $FH;
- my $locale;
- $locale = LedgerSMB::Locale->get_handle('fr');
- ##############
- ## AM tests ##
- ##############
- # AM->check_template_name checks
- # check_template operates by calling $form->error if the checks fail
- $form = new Form;
- $myconfig = {'templates' => 'test'};
- for my $ext ('css', 'tex', 'txt', 'html', 'xml') {
- $form->{file} = "test/apples.${ext}";
- @r = trap{AM->check_template_name($myconfig, $form)};
- ok(!defined $trap->die,
- "AM, check_template_name: Template directory, ${ext}");
- }
- $form->{file} = 'css/apples.txt';
- @r = trap{AM->check_template_name($myconfig, $form)};
- ok(!defined $trap->die,
- 'AM, check_template_name: CSS directory, txt');
- $form->{file} = 'test2/apples.txt';
- @r = trap{AM->check_template_name($myconfig, $form)};
- is($trap->die, "Error: Not in a whitelisted directory: test2/apples.txt\n",
- 'AM, check_template_name: Invalid directory, non-css denial');
- $form->{file} = 'test/apples.exe';
- @r = trap{AM->check_template_name($myconfig, $form)};
- is($trap->die, "Error: Error: File is of type that is not allowed.\n",
- 'AM, check_template_name: Disallowed type denial');
- # adjusting backuppath to avoid triggering directory traversal detection
- $temp = ${LedgerSMB::Sysconfig::backuppath};
- ${LedgerSMB::Sysconfig::backuppath} = "foo";
- $form->{file} = "${LedgerSMB::Sysconfig::backuppath}/apples.txt";
- @r = trap{AM->check_template_name($myconfig, $form)};
- is($trap->die, "Error: Not allowed to access foo/ with this method\n",
- 'AM, check_template_name: Backup path denial');
- ${LedgerSMB::Sysconfig::backuppath} = $temp;
- $form->{file} = "css/../apples.txt";
- @r = trap{AM->check_template_name($myconfig, $form)};
- is($trap->die, "Error: Directory transversal not allowed.\n",
- 'AM, check_template_name: Directory transversal denial 1');
- $form->{file} = "/tmp/apples.txt";
- @r = trap{AM->check_template_name($myconfig, $form)};
- is($trap->die, "Error: Directory transversal not allowed.\n",
- 'AM, check_template_name: Directory transversal denial 2');
- $form->{file} = "test/apples.txt:evil";
- @r = trap{AM->check_template_name($myconfig, $form)};
- is($trap->die, "Error: Directory transversal not allowed.\n",
- 'AM, check_template_name: Directory transversal denial 3');
- $form->{file} = "c:\\evil.txt";
- @r = trap{AM->check_template_name($myconfig, $form)};
- is($trap->die, "Error: Directory transversal not allowed.\n",
- 'AM, check_template_name: Directory transversal denial 4');
- # AM->load_template checks
- # load_template takes its file name from form
- $form = new Form;
- $myconfig = {'templates' => 't/data'};
- $form->{file} = 't/data/04-not-there.txt';
- @r = trap{AM->load_template($myconfig, $form)};
- is($trap->die, "Error: t/data/04-not-there.txt : No such file or directory\n",
- 'AM, load_template: Die on non-existent file');
- $form->{file} = 't/data/04-template.html';
- AM->load_template($myconfig, $form);
- is($form->{body}, "I am a template.\nLook at me <?lsmb login ?>.\n",
- 'AM, load_template: Read existing file');
- # AM->save_template checks
- $form = new Form;
- $myconfig = {'templates' => 't/var/not here'};
- $form->{body} = "I am a template.\nLook at me.\n";
- $form->{file} = "$myconfig->{templates}/test.txt";
- @r = trap{AM->save_template($myconfig, $form)};
- is($trap->die,
- "Error: t/var/not here/test.txt : No such file or directory\n",
- 'AM, save_template: Die on unwritable file');
- $myconfig = {'templates' => 't/var'};
- $form->{body} = "I am a template.\nLook at me.";
- $form->{file} = "$myconfig->{templates}/04-template-save-test-$$.txt";
- ok(!-e $form->{file}, 'AM, save_template: Environment clean');
- AM->save_template($myconfig, $form);
- ok(-e $form->{file}, 'AM, save_template: File created');
- open($FH, '<', $form->{file});
- @r = <$FH>;
- close($FH);
- chomp(@r);
- is(join("\n", @r), $form->{body}, 'AM, save_template: Good save');
- is(unlink($form->{file}), 1, 'AM, save_template: removing testfile');
- ok(!-e $form->{file}, 'AM, save_template: testfile removed');
- ######################################
- ## LedgerSMB::Template::HTML checks ##
- ######################################
- is(LedgerSMB::Template::HTML::get_template('04-template'), '04-template.html',
- 'HTML, get_template: Returned correct template file name');
- is(LedgerSMB::Template::HTML::preprocess('04-template'), '04-template',
- 'HTML, preprocess: Returned simple string unchanged');
- is(LedgerSMB::Template::HTML::preprocess('14 > 12'), '14 > 12',
- 'HTML, preprocess: Returned properly escaped string');
- is_deeply(LedgerSMB::Template::HTML::preprocess([0, 'apple', 'mango&durian']),
- [0, 'apple', 'mango&durian'],
- 'HTML, preprocess: Returned properly escaped array ref contents');
- is_deeply(LedgerSMB::Template::HTML::preprocess({'fruit' => '&veggies',
- 'test' => 1}),
- {'fruit' => '&veggies', 'test' => 1},
- 'HTML, preprocess: Returned properly escaped hash ref contents');
- is_deeply(LedgerSMB::Template::HTML::preprocess({'fruit' => '&veggies',
- 'test' => ['nest', 'bird', '0 < 15', 1]}),
- {'fruit' => '&veggies', 'test' => ['nest', 'bird', '0 < 15', 1]},
- 'HTML, preprocess: Returned properly escaped nested contents');
- is(LedgerSMB::Template::HTML::postprocess({outputfile => '04-template'}),
- '04-template.html', 'HTML, postprocess: Return output filename');
- ####################
- ## Template tests ##
- ####################
- # Template->new
- $myconfig = {'templates' => 't/data'};
- throws_ok{new LedgerSMB::Template('user' => $myconfig, 'language' => 'x/0', 'format' => 'HTML')}
- qr/Invalid language/, 'Template, new: Invalid language caught 1';
- throws_ok{new LedgerSMB::Template('user' => $myconfig, 'language' => '1\\2', 'format' => 'HTML')}
- qr/Invalid language/, 'Template, new: Invalid language caught 2';
- throws_ok{new LedgerSMB::Template('user' => $myconfig, 'language' => '1:2', 'format' => 'HTML')}
- qr/Invalid language/, 'Template, new: Invalid language caught 3';
- throws_ok{new LedgerSMB::Template('user' => $myconfig, 'language' => '..', 'format' => 'HTML')}
- qr/Invalid language/, 'Template, new: Invalid language caught 4';
- throws_ok{new LedgerSMB::Template('user' => $myconfig, 'language' => '.svn', 'format' => 'HTML')}
- qr/Invalid language/,
- 'Template, new: Invalid language caught 5';
- $template = undef;
- $template = new LedgerSMB::Template('user' => $myconfig, 'language' => 'de', 'format' => 'HTML');
- ok(defined $template, 'Template, new: Object creation with valid language');
- isa_ok($template, 'LedgerSMB::Template',
- 'Template, new: Object creation with valid language');
- is($template->{include_path}, 't/data/de;t/data',
- 'Template, new: Object creation with valid language has good include_path');
- $template = undef;
- $template = new LedgerSMB::Template('user' => $myconfig, 'language' => 'de',
- 'path' => 't/data', 'output_file' => 'test', 'format' => 'HTML');
- ok(defined $template,
- 'Template, new: Object creation with valid language and path');
- isa_ok($template, 'LedgerSMB::Template',
- 'Template, new: Object creation with valid language and path');
- is($template->{include_path}, 't/data',
- 'Template, new: Object creation with valid path overrides language');
- is($template->{outputfile}, 't/var/test',
- 'Template, new: Object creation with filename is correct');
- $template = undef;
- $template = new LedgerSMB::Template('user' => $myconfig, 'format' => 'HTML',
- 'template' => '04-template', 'locale' => $locale);
- ok(defined $template,
- 'Template, new: Object creation with locale');
- isa_ok($template, 'LedgerSMB::Template',
- 'Template, new: Object creation with locale');
- $template = undef;
- $template = new LedgerSMB::Template('user' => $myconfig, 'format' => 'HTML',
- 'template' => '04-template-2', 'no_auto_output' => 1);
- ok(defined $template,
- 'Template, new: Object creation with non-existent template');
- throws_ok{$template->render({'login' => 'foo'})} qr/not found/,
- 'Template, render: File not found caught';
- $template = undef;
- $template = new LedgerSMB::Template('user' => $myconfig, 'format' => 'TODO',
- 'template' => '04-template', 'no_auto_output' => 1);
- ok(defined $template,
- 'Template, new: Object creation with non-existent format');
- throws_ok{$template->render({'login' => 'foo'})} qr/Can't locate/,
- 'Template, render: Invalid format caught';
- #####################
- ## Rendering tests ##
- #####################
- $template = undef;
- $template = new LedgerSMB::Template('user' => $myconfig, 'format' => 'PDF',
- 'template' => '04-template', 'no_auto_output' => 1);
- ok(defined $template,
- 'Template, new (PDF): Object creation with format and template');
- isa_ok($template, 'LedgerSMB::Template',
- 'Template, new (PDF): Object creation with format and template');
- is($template->{include_path}, 't/data',
- 'Template, new (PDF): Object creation with format and template');
- is($template->render({'login' => 'foo&bar'}), "t/var/04-template-output-$$.pdf",
- 'Template, render (PDF): Simple PDF template, default filename');
- ok(-e "t/var/04-template-output-$$.pdf",
- 'Template, render (PDF): File created');
- is(unlink("t/var/04-template-output-$$.pdf"), 1,
- 'Template, render (PDF): removing testfile');
- ok(!-e "t/var/04-template-output-$$.pdf",
- 'Template, render (PDF): testfile removed');
- $template = undef;
- $template = new LedgerSMB::Template('user' => $myconfig, 'format' => 'PS',
- 'template' => '04-template', 'no_auto_output' => 1);
- ok(defined $template,
- 'Template, new (PS): Object creation with format and template');
- isa_ok($template, 'LedgerSMB::Template',
- 'Template, new (PS): Object creation with format and template');
- is($template->{include_path}, 't/data',
- 'Template, new (PS): Object creation with format and template');
- is($template->render({'login' => 'foo\&bar'}),
- "t/var/04-template-output-$$.ps",
- 'Template, render (PS): Simple Postscript template, default filename');
- ok(-e "t/var/04-template-output-$$.ps", 'Template, render (PS): File created');
- is(unlink("t/var/04-template-output-$$.ps"), 1,
- 'Template, render (PS): removing testfile');
- ok(!-e "t/var/04-template-output-$$.ps",
- 'Template, render (PS): testfile removed');
- $template = undef;
- $template = new LedgerSMB::Template('user' => $myconfig, 'format' => 'TXT',
- 'template' => '04-template', 'no_auto_output' => 1);
- ok(defined $template,
- 'Template, new (TXT): Object creation with format and template');
- isa_ok($template, 'LedgerSMB::Template',
- 'Template, new (TXT): Object creation with format and template');
- is($template->{include_path}, 't/data',
- 'Template, new (TXT): Object creation with format and template');
- is($template->render({'login' => 'foo&bar'}),
- undef,
- 'Template, render: Simple text template, no filename');
- is($template->{output}, "I am a template.\nLook at me foo&bar.\n",
- 'Template, render (TXT): Simple TXT template, correct output');
- $template = undef;
- $template = new LedgerSMB::Template('user' => $myconfig, 'format' => 'HTML',
- 'template' => '04-template', 'no_auto_output' => 1);
- ok(defined $template,
- 'Template, new (HTML): Object creation with format and template');
- isa_ok($template, 'LedgerSMB::Template',
- 'Template, new (HTML): Object creation with format and template');
- is($template->{include_path}, 't/data',
- 'Template, new (HTML): Object creation with format and template');
- is($template->render({'login' => 'foo&bar'}),
- undef,
- 'Template, render (HTML): Simple HTML template, no file');
- is($template->{output}, "I am a template.\nLook at me foo&bar.",
- 'Template, render (HTML): Simple HTML template, correct output');
- $template = undef;
- $template = new LedgerSMB::Template('user' => $myconfig, 'format' => 'HTML',
- 'template' => \'Look at me <?lsmb login ?>.', 'no_auto_output' => 1);
- ok(defined $template,
- 'Template, new (HTML): Object creation with string template');
- isa_ok($template, 'LedgerSMB::Template',
- 'Template, new (HTML): Object creation with string template');
- is($template->{include_path}, 't/data',
- 'Template, new (HTML): Object creation with string template');
- is($template->render({'login' => 'foo&bar'}),
- undef,
- 'Template, render (HTML): Simple HTML string template, no file');
- is($template->{output}, "Look at me foo&bar.",
- 'Template, render (HTML): Simple HTML string template, correct output');
- $template = undef;
- $template = new LedgerSMB::Template('user' => $myconfig, 'format' => 'HTML',
- 'template' => '04-gettext', 'output_file' => '04-gettext',
- 'no_auto_output' => 1);
- ok(defined $template,
- 'Template, new (HTML): Object creation with outputfile');
- isa_ok($template, 'LedgerSMB::Template',
- 'Template, new (HTML): Object creation with outputfile');
- is($template->{include_path}, 't/data',
- 'Template, new (HTML): Object creation with outputfile');
- is($template->render({'month' => 'June', 'login' => 'foo&bar',
- 'fr' => $locale}), 't/var/04-gettext.html',
- 'Template, render (HTML): Gettext HTML template');
- ok(-e "t/var/04-gettext.html",
- 'Template, render (HTML): File created');
- open($FH, '<', "t/var/04-gettext.html");
- @r = <$FH>;
- close($FH);
- chomp(@r);
- is(join("\n", @r),
- "I am a foo&bar.\nLook at me Juin.\njuni\nAan foo&bar",
- 'Template, render (HTML): Gettext HTML template, correct output');
- is(unlink("t/var/04-gettext.html"), 1,
- 'Template, render (HTML): removing testfile');
- ok(!-e "t/var/04-gettext.html",
- 'Template, render (HTML): testfile removed');
- ## XeTeX test, requires PDFLATEX to be xelatex and modified Template::Latex
- SKIP: {
- skip 'XeTeX and modified Template::Latex requiring PDF tests';
- $template = undef;
- $template = new LedgerSMB::Template('user' => $myconfig,
- 'format' => 'PDF', 'template' => '04-gettext',
- 'no_auto_output' => 1);
- ok(defined $template,
- 'Template, new (PDF): XeTeX template creation');
- isa_ok($template, 'LedgerSMB::Template',
- 'Template, new (PDF): XeTeX template creation');
- is($template->{include_path}, 't/data',
- 'Template, new (PDF): XeTeX template creation');
- is($template->render({'login' => 'foo&bar'}),
- "t/var/04-gettext-output-$$.pdf",
- 'Template, render (PDF): XeTeX PDF template, default filename');
- ok(-e "t/var/04-gettext-output-$$.pdf",
- 'Template, render (PDF): File created');
- is(unlink("t/var/04-gettext-output-$$.pdf"), 1,
- 'Template, render (PDF): removing testfile');
- ok(!-e "t/var/04-gettext-output-$$.pdf",
- 'Template, render (PDF): testfile removed');
- }
- #########################################
- ## LedgerSMB::Template private methods ##
- #########################################
- use Math::BigFloat;
- $template = undef;
- $template = new LedgerSMB::Template('user' => {numberformat => '1.000,00'},
- 'format' => 'HTML', 'template' => '04-template', 'no_auto_output' => 1);
- ok(defined $template,
- 'Template, private (_preprocess): Object creation with format and template');
- isa_ok($template, 'LedgerSMB::Template',
- 'Template, private (_preprocess): Object creation with format and template');
- my $number = Math::BigFloat->new(17.5);
- isa_ok($number, 'Math::BigFloat',
- 'Template, private (_preprocess): number');
- $template->_preprocess($number);
- ## Commenting out these tests since currently the functionality is known broken
- ## and unused
- #cmp_ok($number, 'eq', '17,50',
- # 'Template, private (_preprocess): Math::BigFloat conversion');
- #$number = [Math::BigFloat->new(1008.51), 'hello'];
- #$template->_preprocess($number);
- #
- #cmp_ok($number->[0], 'eq', '1.008,51',
- # 'Template, private (_preprocess): Math::BigFloat conversion (array)');
- #cmp_ok($number->[1], 'eq', 'hello',
- # 'Template, private (_preprocess): no conversion (array)');
- ###################################
- ## LedgerSMB::Template::Elements ##
- ###################################
- $template = undef;
- $form = undef;
- my $lsmb = LedgerSMB->new();
- $locale = LedgerSMB::Locale->get_handle( ${LedgerSMB::Sysconfig::language} )
- or $lsmb->error( __FILE__ . ':' . __LINE__ . ": Locale not loaded: $!\n" );
- $template = new LedgerSMB::Template('user' => {numberformat => '1.000,00'},
- 'format' => 'HTML', path => 't/data', locale => $locale, 'template' => '04-complex_template', 'no_auto_output' => 1);
- $template->render({});
- my $contact_request = {
- entity_id => 1,
- control_code => 'test1',
- meta_number => 'test1',
- credit_id => '1',
- entity_class => 1,
- credit_list => [{ entity_class => 1,
- meta_number => 'test1',
- }],
- contacts => [{contact => 'ctest1',
- description => 'dtest1',
- contact_class => '1'}],
- business_id => 1000,
- business_types => [{ id => 1, description => 'test1' },
- { id => 1000, description => 'test2' }],
- }; # Company with Credit Accounts and business types.
- my $contact_template = LedgerSMB::Template->new(
- path => 'UI/Contact',
- template => 'contact',
- format => 'HTML',
- no_auto_output => 1,
- output_file => 'contact_test1'
- );
- $contact_template->render($contact_request);
- my @output = get_output_line_array($contact_template);
- is(grep (/value="1" selected/, @output), 0, 'Select box Value 1 unselected');
- is(grep (/value="1000" selected/, @output), 1, 'Select box Value 1000 selected');
- is(grep (/<td class="description">dtest1/, @output), 1, 'Contact description shows');
- # LPR PRinting Tests
- use LedgerSMB::Sysconfig;
- %LedgerSMB::Sysconfig::printer = ('test' => 'cat > t/var/04-lpr-test');
- $template = new LedgerSMB::Template('user' => $myconfig, 'format' => 'PDF',
- 'template' => '04-template', 'locale' => $locale, no_auto_output => 1);
- $template->render({media => 'test'});
- $template->output(media => 'test');
- ok (open (LPR_TEST, '<', 't/var/04-lpr-test'), 'LedgerSMB::Template::_output_lpr output file opened successfully');
- my $line1 = <LPR_TEST>;
- like($line1, qr/^%PDF/, 'output file is pdf');
- # Functions
- sub get_output_line_array {
- my $FH;
- my ($template) = @_;
- open($FH, '<:bytes', $template->{rendered}) or
- throw Error::Simple 'Unable to open rendered file';
- my @lines = <$FH>;
- close $FH;
- delete $template->{rendered};
- return @lines;
- }
|