#!/usr/bin/perl -w use strict; use Test::More tests => 30; use Test::MockModule; require_ok('CGI::Maypole'); ok($CGI::Maypole::VERSION, 'defines $VERSION'); ok($INC{'CGI/Simple.pm'}, 'requires CGI::Simple'); ok($INC{'Maypole/Headers.pm'}, 'requires Maypole::Headers'); ok(CGI::Maypole->isa('Maypole'), '@ISA = Maypole'); my %calls; my $mock_maypole = new Test::MockModule('CGI::Maypole'); my $mock_cgi = new Test::MockModule('CGI::Simple'); $mock_cgi->mock(path_info => sub { delete $_[0]->{'.path_info'}; my $orig_path_info = $mock_cgi->original('path_info'); goto $orig_path_info; }); # run() can_ok('CGI::Maypole' => 'run'); $mock_maypole->mock(handler => sub {$calls{handler} = \@_; 'X'}); my $status = CGI::Maypole->run('TEST'); ok($calls{handler}, '... calls handler()'); is_deeply($calls{handler}, ['CGI::Maypole'], '... as a method, passing 0 arguments'); is($status, 'X', '... and returns its status'); my $r = bless {}, 'CGI::Maypole'; $r->headers_out(Maypole::Headers->new); $ENV{HTTP_HOST} = 'localhost'; $ENV{SCRIPT_NAME} = '/maypole/index.cgi'; $ENV{PATH_INFO} = '/'; $ENV{REQUEST_METHOD} = 'GET'; $ENV{QUERY_STRING} = 'beer=1;beer=2;pub=red+lion;handpump'; $ENV{DOCUMENT_ROOT} = '/var/tmp/maypole'; for (keys %ENV) { delete $ENV{$_} if /^HTTPS?/; } # get_request() can_ok($r => 'get_request'); my $cgi = $r->get_request; isa_ok($cgi, 'CGI::Simple', '... returns a CGI::Simple object'); is($cgi, $r->{cgi}, '... and stores it in the "cgi" slot'); # parse_location() can_ok($r => 'parse_location'); $ENV{HTTP_REFERER} = 'http://maypole.perl.org/'; $ENV{HTTP_USER_AGENT} = 'tty'; $r->parse_location; is($r->headers_in->get('Referer'), 'http://maypole.perl.org/', '... sets headers_in() from HTTP variables'); is_deeply([$r->headers_in->field_names], [qw(Referer User-Agent)], '... loads only those HTTP variables'); is($r->path, 'frontpage', '... sets "path" to frontpage if undefined'); #delete $r->{cgi}{'.path_info'}; $ENV{PATH_INFO} = '/brewery/view/1/2/3'; $r->parse_location; is($r->path, 'brewery/view/1/2/3', '... path is PATH_INFO without leading /'); is($r->table, 'brewery', '... sets "table" to first part of PATH_INFO'); is($r->action, 'view', '... sets "action" to second part of PATH_INFO'); is_deeply($r->args, [1,2,3], '... sets "args" to a list of remaining path segments'); $mock_maypole->mock( parse_path => sub {$calls{parse_path} = \@_}, parse_args => sub {$calls{parse_args} = \@_}, ); $r->parse_location; is_deeply($calls{parse_path}, [$r], '... calls parse_path'); is_deeply($calls{parse_args}, [$r], '... calls parse_args'); # parse_args() $mock_maypole->unmock('parse_args'); can_ok($r => 'parse_args'); $cgi->parse_query_string; $r->parse_args; is_deeply($r->params, { beer => [1,2], pub => 'red lion', handpump => undef }, '... parsed params'); is_deeply($r->params, $r->query, '... query and params are identical'); # send_output() can_ok($r => 'send_output'); SKIP: { eval "require IO::CaptureOutput"; skip "IO::CaptureOutput not installed", 2 if $@; $r->content_type('text/plain'); $r->document_encoding('iso8859-1'); $r->output('Hello World!'); my $stdout; eval { IO::CaptureOutput::capture(sub {$r->send_output}, \$stdout); }; diag $@ if $@; my $compare = join "\cM\cJ", 'Content-length: 12', 'Content-Type: text/plain; charset=iso8859-1', '', 'Hello World!'; is($stdout, $compare, '... prints output, including content-type header'); # test custom output headers $r->headers_out->set(X_Bender => 'kiss my shiny metal ass'); eval { IO::CaptureOutput::capture(sub {$r->send_output}, \$stdout); }; diag $@ if $@; $compare = join "\cM\cJ", 'Content-length: 12', 'X-bender: kiss my shiny metal ass', 'Content-Type: text/plain; charset=iso8859-1', '', 'Hello World!'; is($stdout, $compare, '... prints output, including custom headers'); } # get_template_root() can_ok($r => 'get_template_root'); is($r->get_template_root(), '/var/tmp/maypole/index.cgi', '... catdir(document_root, [relative_url])');