Mojolicious

 view release on metacpan or  search on metacpan

t/mojolicious/lite_app.t  view on Meta::CPAN

# Render action
$t->get_ok('/action_template')->status_is(200)->header_is(Server => 'Mojolicious (Perl)')
  ->content_is("controller and action!\n");

# Dead action
$t->get_ok('/dead')->status_is(500)->header_is(Server => 'Mojolicious (Perl)')->content_like(qr/works!/);

# Dead renderer
$t->get_ok('/dead_renderer')->status_is(500)->header_is(Server => 'Mojolicious (Perl)')
  ->content_like(qr/renderer works!/);

# Dead renderer with auto rendering
$t->get_ok('/dead_auto_renderer')->status_is(500)->header_is(Server => 'Mojolicious (Perl)')
  ->content_like(qr/renderer works!/);

# Dead template
$t->get_ok('/dead_template')->status_is(500)->header_is(Server => 'Mojolicious (Perl)')->content_like(qr/works too!/);

# Handler that changes status
$t->get_ok('/handler_change_status')->status_is(500)->content_is("Bad\n");

# Template that changes status
$t->get_ok('/template_change_status')->status_is(500)->content_is("Bad\n");

# Regex in name
$t->get_ok('/regex/in/template')->status_is(200)->header_is(Server => 'Mojolicious (Perl)')
  ->content_is("test(test)(\\Qtest\\E)(\n");

# Chunked response with basic auth
$t->get_ok('//sri:foo@/stream' => form => {foo => 'bar'})->status_is(200)->header_is(Server => 'Mojolicious (Perl)')
  ->content_like(qr!^foobarsri:foohttp://127\.0\.0\.1:\d+/stream$!);

# Ajax
$t->get_ok('/maybe/ajax')->status_is(200)->header_is(Server => 'Mojolicious (Perl)')->content_is('not ajax');
$t->get_ok('/maybe/ajax' => {'X-Requested-With' => 'XMLHttpRequest'})->status_is(200)
  ->header_is(Server => 'Mojolicious (Perl)')->content_is('is ajax');

# With finish event
my $stash;
$t->app->plugins->once(before_dispatch => sub { $stash = shift->stash });
$t->get_ok('/finished')->status_is(200)->header_is(Server => 'Mojolicious (Perl)')->content_is('so far so good!');
Mojo::IOLoop->one_tick until $stash->{finished};
is $stash->{finished}, 1, 'finish event has been emitted once';

# IRI
$t->get_ok('/привет/мир')->status_is(200)->content_type_is('text/html;charset=UTF-8')->content_is('привет мир');

# Route with format
$t->get_ok('/root.html')->status_is(200)->header_is(Server => 'Mojolicious (Perl)')->content_is("/\n");

# Fallback route without format
$t->get_ok('/root')->status_is(200)->header_is(Server => 'Mojolicious (Perl)')->content_is('root fallback!');
$t->get_ok('/root.txt')->status_is(200)->header_is(Server => 'Mojolicious (Perl)')->content_is('root fallback!');

# Root with format
$t->get_ok('/.html')->status_is(200)->header_exists_not('Servers')
  ->header_exists_not('Servers', 'the header is missing')->header_exists('Server')
  ->header_exists('Server', 'the header exists')->header_is(Server => 'Mojolicious (Perl)')
  ->content_is("/root.html\n/root.html\n/root.html\n/root.html\n/root.html\n");

subtest 'Reverse proxy with "X-Forwarded-For"' => sub {
  local $ENV{MOJO_REVERSE_PROXY} = 1;
  my $t = Test::Mojo->new;
  $t->get_ok('/0' => {'X-Forwarded-For' => '192.0.2.2, 192.0.2.1'})->status_is(200)
    ->header_unlike('X-Original' => qr/192\.0\.2\.1/)->content_like(qr!http://127\.0\.0\.1:\d+/0-192\.0\.2\.1-0$!);
};

subtest 'Reverse proxy with "X-Forwarded-For" and trusted proxies' => sub {
  local $ENV{MOJO_TRUSTED_PROXIES} = '127.0.0.1, 192.0.2.1';
  my $t = Test::Mojo->new;
  $t->get_ok('/0' => {'X-Forwarded-For' => '192.0.2.2, 192.0.2.1'})->status_is(200)
    ->header_unlike('X-Original' => qr/192\.0\.2\.(?:2|1)/)
    ->content_like(qr!http://127\.0\.0\.1:\d+/0-192\.0\.2\.2-0$!);
};

subtest 'Reverse proxy with "X-Forwarded-For" and trusted proxies (untrusted original)' => sub {
  local $ENV{MOJO_TRUSTED_PROXIES} = '192.0.2.1';
  my $t = Test::Mojo->new;
  $t->get_ok('/0' => {'X-Forwarded-For' => '192.0.2.2, 192.0.2.1'})->status_is(200)
    ->header_unlike('X-Original' => qr/192\.0\.2\.(?:2|1)/)
    ->content_like(qr!http://127\.0\.0\.1:\d+/0-127\.0\.0\.1-0$!);
};

subtest 'Reverse proxy with "X-Forwarded-For" and trusted proxy networks' => sub {
  local $ENV{MOJO_TRUSTED_PROXIES} = '127.0.0.0/8, 192.0.2.1/32';
  my $t = Test::Mojo->new;
  $t->get_ok('/0' => {'X-Forwarded-For' => '192.0.2.2, 192.0.2.1'})->status_is(200)
    ->header_unlike('X-Original' => qr/192\.0\.2\.(?:2|1)/)
    ->content_like(qr!http://127\.0\.0\.1:\d+/0-192\.0\.2\.2-0$!);
};

subtest 'Reverse proxy with "X-Forwarded-For" and trusted proxies (all addresses trusted)' => sub {
  local $ENV{MOJO_TRUSTED_PROXIES} = '0.0.0.0/0';
  my $t = Test::Mojo->new;
  $t->get_ok('/0' => {'X-Forwarded-For' => '192.0.2.2, 192.0.2.1'})->status_is(200)
    ->header_unlike('X-Original' => qr/192\.0\.2\.(?:2|1)/)
    ->content_like(qr!http://127\.0\.0\.1:\d+/0-192\.0\.2\.2-0$!);
};

subtest 'Reverse proxy with "X-Forwarded-For" and trusted proxies (unexpected leading address)' => sub {
  local $ENV{MOJO_TRUSTED_PROXIES} = '127.0.0.0/8, 192.0.2.1';
  my $t = Test::Mojo->new;
  $t->get_ok('/0' => {'X-Forwarded-For' => '7.7.7.7, 192.0.2.2, 192.0.2.1'})->status_is(200)
    ->header_unlike('X-Original' => qr/192\.0\.2\.(?:2|1)/)
    ->content_like(qr!http://127\.0\.0\.1:\d+/0-192\.0\.2\.2-0$!);
};

subtest 'Reverse proxy with "X-Forwarded-Proto"' => sub {
  local $ENV{MOJO_REVERSE_PROXY} = 1;
  my $t = Test::Mojo->new;
  $t->get_ok('/0' => {'X-Forwarded-Proto' => 'https'})->status_is(200)->content_like(qr!^https://127\.0\.0\.1:\d+/0-!)
    ->content_like(qr/-0$/)->content_unlike(qr!-192\.0\.2\.1-0$!);
};

# "X-Forwarded-For"
$t->ua->server->restart;
$t->get_ok('/0' => {'X-Forwarded-For' => '192.0.2.2, 192.0.2.1'})->status_is(200)
  ->content_like(qr!^http://127\.0\.0\.1:\d+/0-!)->content_like(qr/-0$/)->content_unlike(qr!-192\.0\.2\.1-0$!);

# "X-Forwarded-Proto"
$t->get_ok('/0' => {'X-Forwarded-Proto' => 'https'})->status_is(200)->content_like(qr!^http://127\.0\.0\.1:\d+/0-!)
  ->content_like(qr/-0$/)->content_unlike(qr!-192\.0\.2\.1-0$!);

# "continue" keyword in template
$t->get_ok('/continue')->status_is(200)->content_like(qr/1.+2.+3/s);

# Inline "epl" template
$t->delete_ok('/inline/epl')->status_is(200)->content_is("2 ☃\n");

# Inline "ep" template
$t->get_ok('/inline/ep?foo=bar')->status_is(200)->content_is("barworks!\n");

# Inline "ep" template "0"
$t->get_ok('/inline/ep/too')->status_is(200)->content_is("0\n");

# Inline template with include
$t->get_ok('/inline/ep/include')->status_is(200)->content_is("♥just ♥\nworks!\n");

# Rewritten localized arguments
$t->get_ok('/to_string')->status_is(200)->content_is('beforeafter');

# Render static file outside of public directory
$t->get_ok('/source')->status_is(200)->content_type_is('application/octet-stream')->content_like(qr!get_ok\('/source!);

# File does not exist
$logs = app->log->capture('trace');
$t->get_ok('/source?fail=1')->status_is(500)->content_like(qr/Static file "does_not_exist.txt" not found/);
like $logs, qr/Static file "does_not_exist.txt" not found/, 'right message';
undef $logs;

# With body and max message size
{
  local $ENV{MOJO_MAX_MESSAGE_SIZE} = 1024;
  my $logs = app->log->capture('trace');
  $t->get_ok('/', '1234' x 1024)->status_is(200)->header_is(Connection => 'close')
    ->content_is("Maximum message size exceeded\n" . "/root.html\n/root.html\n/root.html\n/root.html\n/root.html\n");
  like $logs, qr/Maximum message size exceeded/, 'right message';
  undef $logs;
}

# Relaxed placeholder
$t->get_ok('/foo_relaxed/123')->status_is(200)->content_is('1230');
$t->get_ok('/foo_relaxed/123.html')->status_is(200)->content_is('123.html0');
$t->get_ok('/foo_relaxed/123' => {DNT => 1})->status_is(200)->content_is('1231');
$t->get_ok('/foo_relaxed/')->status_is(404);

# Wildcard placeholder
$t->get_ok('/foo_wildcard/123')->status_is(200)->content_is('123');
$t->get_ok('/foo_wildcard/IQ==%0A')->status_is(200)->content_is("IQ==\x0a");
$t->get_ok('/foo_wildcard/')->status_is(404);
$t->get_ok('/foo_wildcard_too/123')->status_is(200)->content_is('123');
$t->get_ok('/foo_wildcard_too/')->status_is(404);

# Header conditions
$t->get_ok('/with/header/condition', {'X-Secret-Header' => 'bar', 'X-Another-Header' => 'baz'})->status_is(200)
  ->content_is("Test ok!\n");
$t->get_ok('/with/header/condition')->status_is(404)->content_like(qr/Oops!/);

 view all matches for this distribution
 view release on metacpan -  search on metacpan

( run in 0.456 second using v1.00-cache-2.02-grep-82fe00e-cpan-c30982ac1bc3 )