Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages


home | help
Dancer2::Test(3)      User Contributed Perl Documentation     Dancer2::Test(3)

       Dancer2::Test - Useful routines for testing Dancer2 apps

       version 0.300004

	   use Test::More;
	   use Plack::Test;
	   use HTTP::Request::Common; #	install	separately

	   use YourDancerApp;

	   my $app  = YourDancerApp->to_app;
	   my $test = Plack::Test->create($app);

	   my $res = $test->request( GET '/' );
	   is( $res->code, 200,	'[GET /] Request successful' );
	   like( $res->content,	qr/hello, world/, '[GET	/] Correct content' );


       DEPRECATED. This	module and all the functions listed below are
       deprecated. Do not use this module. The routines	provided by this
       module for testing Dancer2 apps are buggy and unnecessary. Instead, use
       the Plack::Test module as shown in the SYNOPSIS above and ignore	the
       functions in this documentation.	Consult	the Plack::Test	documentation
       for further details.

       This module will	be removed from	the Dancer2 distribution in the	near
       future.	You should migrate all tests that use it over to the
       Plack::Test module and remove this module from your system. This	module
       will throw warnings to remind you.

       For now,	you can	silence	the warnings by	setting	the "NO_WARN" option:

	   $Dancer::Test::NO_WARN = 1;

       In the functions	below, $test_name is always optional.

   dancer_response ($method, $path, $params, $arg_env);
       Returns a Dancer2::Core::Response object	for the	given request.

       Only $method and	$path are required.

       $params is a hashref with 'body'	as a string; 'headers' can be an
       arrayref	or a HTTP::Headers object, 'files' can be arrayref of hashref,
       containing some files to	upload:

	   dancer_response($method, $path,
		   params => $params,
		   body	=> $body,
		   headers => $headers,
		   files => [ {	filename => '/path/to/file', name => 'my_file' } ],

       A good reason to	use this function is for testing POST requests.	Since
       POST requests may not be	idempotent, it is necessary to capture the
       content and status in one shot. Calling the response_status_is and
       response_content_is functions in	succession would make two requests,
       each of which could alter the state of the application and cause
       Schrodinger's cat to die.

	   my $response	= dancer_response POST => '/widgets';
	   is $response->status, 202, "response	for POST /widgets is 202";
	   is $response->content, "Widget #1 has been scheduled	for creation",
	       "response content looks good for	first POST /widgets";

	   $response = dancer_response POST => '/widgets';
	   is $response->status, 202, "response	for POST /widgets is 202";
	   is $response->content, "Widget #2 has been scheduled	for creation",
	       "response content looks good for	second POST /widgets";

       It's possible to	test file uploads:

	   post	'/upload' => sub { return upload('image')->content };

	   $response = dancer_response(POST => '/upload', {files => [{name => 'image', filename	=> '/path/to/image.jpg'}]});

       In addition, you	can supply the file contents as	the "data" key:

	   my $data  = 'A test string that will	pretend	to be file contents.';
	   $response = dancer_response(POST => '/upload', {
	       files =>	[{name => 'test', filename => "filename.ext", data => $data}]

       You can also supply a hashref of	headers:

	   headers => {	'Content-Type' => 'text/plain' }

   response_status_is ($request, $expected, $test_name);
       Asserts that Dancer2's response for the given request has a status
       equal to	the one	given.

	   response_status_is [GET => '/'], 200, "response for GET / is	200";

   route_exists([$method, $path], $test_name)
       Asserts that the	given request matches a	route handler in Dancer2's
       registry. If the	route would have returned a 404, the route still
       exists and this test will pass.

       Note that because Dancer2 uses the default route	handler
       Dancer2::Handler::File to match files in	the public folder when no
       other route matches, this test will always pass.	 You can disable the
       default route handlers in the configs but you probably want
       "response_status_is" in Dancer2::Test or	"dancer_response" in

	   route_exists	[GET =>	'/'], "GET / is	handled";

   route_doesnt_exist([$method,	$path],	$test_name)
       Asserts that the	given request does not match any route handler in
       Dancer2's registry.

       Note that this test is likely to	always fail as any route not matched
       will be handled by the default route handler in Dancer2::Handler::File.
       This can	be disabled in the configs.

	   route_doesnt_exist [GET => '/bogus_path'], "GET /bogus_path is not handled";

   response_status_isnt([$method, $path], $status, $test_name)
       Asserts that the	status of Dancer2's response is	not equal to the one

	   response_status_isnt	[GET =>	'/'], 404, "response for GET / is not a	404";

   response_content_is([$method, $path], $expected, $test_name)
       Asserts that the	response content is equal to the $expected string.

	response_content_is [GET => '/'], "Hello, World",
	       "got expected response content for GET /";

   response_content_isnt([$method, $path], $not_expected, $test_name)
       Asserts that the	response content is not	equal to the $not_expected

	   response_content_isnt [GET => '/'], "Hello, World",
	       "got expected response content for GET /";

   response_content_like([$method, $path], $regexp, $test_name)
       Asserts that the	response content for the given request matches the
       regexp given.

	   response_content_like [GET => '/'], qr/Hello, World/,
	       "response content looks good for	GET /";

   response_content_unlike([$method, $path], $regexp, $test_name)
       Asserts that the	response content for the given request does not	match
       the regexp given.

	   response_content_unlike [GET	=> '/'], qr/Page not found/,
	       "response content looks good for	GET /";

   response_content_is_deeply([$method,	$path],	$expected_struct, $test_name)
       Similar to response_content_is(), except	that if	response content and
       $expected_struct	are references,	it does	a deep comparison walking each
       data structure to see if	they are equivalent.

       If the two structures are different, it will display the	place where
       they start differing.

	   response_content_is_deeply [GET => '/complex_struct'],
	       { foo =>	42, bar	=> 24},
	       "got expected response structure	for GET	/complex_struct";

   response_is_file ($request, $test_name);
   response_headers_are_deeply([$method, $path], $expected, $test_name)
       Asserts that the	response headers data structure	equals the one given.

	   response_headers_are_deeply [GET => '/'], [ 'X-Powered-By' => 'Dancer2 1.150' ];

   response_headers_include([$method, $path], $expected, $test_name)
       Asserts that the	response headers data structure	includes some of the
       defined ones.

	   response_headers_include [GET => '/'], [ 'Content-Type' => 'text/plain' ];

       Returns a structure describing pod coverage in your apps

       for one app like	this:

	   package t::lib::TestPod;
	   use Dancer2;

	   =head1 NAME


	   =head2 ROUTES



	   =item get "/in_testpod"



	   get '/in_testpod' =>	sub {
	       return 'get in_testpod';

	   get '/hello'	=> sub {
	       return "hello world";

	   =item post '/in_testpod/*'

	   post	in_testpod


	   post	'/in_testpod/*'	=> sub {
	       return 'post in_testpod';


	   =head2 SPECIALS

	   =head3 PUBLIC


	   =item get "/me:id"


	   get "/me:id"	=> sub {
	       return "ME";


	   =head3 PRIVAT


	   =item post "/me:id"

	   post	/me:id


	   post	"/me:id" => sub	{
	       return "ME";





       would return something like:

	       't::lib::TestPod' => {
		   'has_pod'		 => 1,
		   'routes'		 => [
		       "post /in_testpod/*",
		       "post /me:id",
		       "get /in_testpod",
		       "get /hello",
		       "get /me:id"
		   'undocumented_routes' => [
		       "get /hello"

   is_pod_covered('is pod covered')
       Asserts that your apps have pods	for all	routes

	   is_pod_covered 'is pod covered'

       to avoid	test failures, you should document all your routes with	one of
       the following: head1, head2,head3,head4,	item.


	   =item get '/login'

	   route to login


	   if you use:

	   any '/myaction' => sub {
	       # code


	   any ['get', 'post'] => '/myaction' => sub {
	       # code

	   you need to create pods for each one	of the routes created there.

       When Dancer2::Test is imported, it should be passed all the
       applications that are supposed to be tested.

       If none passed, then the	caller is supposed to be the sole application
       to test.

	   # t/sometest.t

	   use t::lib::Foo;
	   use t::lib::Bar;

	   use Dancer2::Test apps => ['t::lib::Foo', 't::lib::Bar'];

       Dancer Core Developers

       This software is	copyright (c) 2020 by Alexis Sukrieh.

       This is free software; you can redistribute it and/or modify it under
       the same	terms as the Perl 5 programming	language system	itself.

perl v5.32.1			  2020-05-27		      Dancer2::Test(3)


Want to link to this manual page? Use this URL:

home | help