Kelp
view release on metacpan or search on metacpan
lib/Kelp/Test.pm view on Meta::CPAN
is $self->res->header($header), $value, $test_name
|| $self->diag_headers();
return $self;
}
sub header_isnt
{
my ($self, $header, $value, $test_name) = @_;
local $Test::Builder::Level = $Test::Builder::Level + 1;
$test_name ||= "Header '$header' is not '$value'";
isnt $self->res->header($header), $value, $test_name
|| $self->diag_headers();
return $self;
}
sub header_like
{
my ($self, $header, $regexp, $test_name) = @_;
local $Test::Builder::Level = $Test::Builder::Level + 1;
$test_name ||= "Header '$header' =~ $regexp";
like $self->res->header($header), $regexp, $test_name
|| $self->diag_headers();
return $self;
}
sub header_unlike
{
my ($self, $header, $regexp, $test_name) = @_;
local $Test::Builder::Level = $Test::Builder::Level + 1;
$test_name ||= "Header '$header' !~ $regexp";
unlike $self->res->header($header), $regexp, $test_name
|| $self->diag_headers();
return $self;
}
sub json_content
{
my $self = shift;
my $result;
my $decoder = $self->app->get_encoder(json => 'internal');
try {
$result = $decoder->decode(
$self->_decode($self->res->content)
);
}
catch {
fail("Poorly formatted JSON");
};
return $result;
}
sub json_cmp
{
my ($self, $expected, $test_name) = @_;
local $Test::Builder::Level = $Test::Builder::Level + 1;
$test_name ||= "JSON structure matches";
like $self->res->header('content-type'), qr/json/, 'Content-Type is JSON'
or return $self;
my $json = $self->json_content;
cmp_deeply($json, $expected, $test_name) or diag explain $json;
return $self;
}
sub note
{
my $self = shift;
Test::More::note @_;
return $self;
}
sub diag_headers
{
my $self = shift;
diag $self->res->headers->as_string;
return $self;
}
sub diag_content
{
my $self = shift;
diag $self->res->content;
return $self;
}
1;
__END__
=pod
=head1 NAME
Kelp::Test - Automated tests for a Kelp web app
=head1 SYNOPSIS
use MyApp;
use Kelp::Test;
use HTTP::Request::Common;
my $app = MyApp->new;
my $t = Kelp::Test->new( app => $app );
$t->request( GET '/path' )
->code_is(200)
->content_is("It works");
$t->request( POST '/api' )
->json_cmp({auth => 1});
# automatically sets wide output for Test::More (disables Wide character warnings)
use Kelp::Test -utf8;
=head1 DESCRIPTION
This module provides basic tools for testing a Kelp based web application. It
is object oriented, and all methods return C<$self>, so they can be chained
lib/Kelp/Test.pm view on Meta::CPAN
$t->request( POST '/api', [ user => 'jane' ] );
This method returns C<$self>, so other methods can be chained after it.
=head2 request_ok
C<request_ok( $http_request, $test_name )>
Runs C<request>, then tests if the response code is 200. Equivalent to the following
code:
$t->request( GET '/path' )->code_is(200);
$t->request_ok( GET '/path' ); # Same as the above
=head2 code_is, code_isnt
C<code_is( $code, $test_name )>, C<code_isnt( $code, $test_name )>
Tests if the last response returned a status code equal or not equal to C<$code>.
An optional name of the test can be added as a second parameter.
$t->request( GET '/path' )->code_is(200);
$t->request( GET '/path' )->code_isnt(500);
=head2 request_ok
Same as L</request>, but also runs C<code_is(200)>.
$t->request_ok( GET '/home' );
# Tests for code = 200
=head2 content_is, content_isnt
C<content_is( $value, $test_name )>, C<content_isnt( $value, $test_name )>
Tests if the last response returned content equal or not equal to C<$value>.
An optional name of the test can be added as a second parameter.
$t->request( GET '/path' )->content_is("Ok.");
$t->request( GET '/path' )->content_isnt("Fail.");
=head2 content_bytes_are
Same as C<content_is>, but the result is not decoded and the values are
compared byte by byte as hex-encoded string.
=head2 content_like, content_unlike
C<content_like( $regexp, $test_name )>, C<content_unlike( $regexp, $test_name )>
Tests if the last response returned content that matches or doesn't match C<$regexp>.
An optional name of the test can be added as a second parameter.
$t->request( GET '/path' )->content_like(qr{Amsterdam});
$t->request( GET '/path' )->content_unlike(qr{Rotterdam});
=head2 content_type_is, content_type_isnt
C<content_type_is( $value, $test_name )>, C<content_type_isnt( $value, $test_name )>
Tests if the last response's content-type header is equal or not equal to C<$value>.
An optional name of the test can be added as a second parameter.
$t->request( GET '/path' )->content_type_is("text/plain");
$t->request( GET '/path' )->content_type_isnt("text/html");
=head2 full_content_type_is
Like L</content_type_is>, but checks the full content type (with charset).
=head2 header_is, header_isnt
C<header_is( $header, $value, $test_name )>, C<header_isnt( $header, $value, $test_name )>
Tests if the last response returned a header C<$header> that is equal or not
equal to C<$value>. An optional name of the test can be added as a second parameter.
$t->request( GET '/path' )->header_is( "Pragma", "no-cache" );
$t->request( GET '/path' )->header_isnt( "X-Check", "yes" );
=head2 header_like, header_unlike
C<header_like( $header, $regexp, $test_name )>, C<header_unlike( $header, $regexp, $test_name )>
Tests if the last response returned a header C<$header> that matches or doesn't
match C<$regexp>. An optional name of the test can be added as a second parameter.
$t->request( GET '/path' )->header_like( "Content-Type", qr/json/ );
$t->request( GET '/path' )->header_unlike( "Content-Type", qr/image/ );
=head2 json_content
C<json_content()>
Returns the content decoded as JSON. Does not perform any checks, but may
C<fail()> and return C<undef> if the JSON decoding fails.
=head2 json_cmp
C<json_cmp( $expected, $test_name )>
This tests for two things: If the returned C<content-type> is
C<application-json>, and if the returned JSON structure matches the structure
specified in C<$expected>. To compare the two structures this method uses
C<cmp_deeply> from L<Test::Deep>, so you can use all the goodies from the
C<SPECIAL-COMPARISONS-PROVIDED> section of the Test::Deep module.
$t->request( GET '/api' )->json_cmp(
{
auth => 1,
timestamp => ignore(),
info => subhashof( { name => 'Rick James' } )
}
);
An optional name of the test can be added as a second parameter.
=head2 note
C<note( $note )>
Print a note, using the L<Test::More> C<note> function.
$t->request( GET '/path' )
->note("Checking headers now")
->header_is( "Content-Type", qr/json/ );
=head2 diag_headers
Prints all headers for debugging purposes.
$t->request( GET '/path' )
->header_is( "Content-Type", qr/json/ )
->diag_headers();
=head2 diag_content
Prints the entire content for debugging purposes.
$t->request( GET '/path' )
->content_is("Well")
->diag_content();
=cut
( run in 0.758 second using v1.01-cache-2.11-cpan-d7f47b0818f )