1Dancer2::Test(3)      User Contributed Perl Documentation     Dancer2::Test(3)
2
3
4

NAME

6       Dancer2::Test - Useful routines for testing Dancer2 apps
7

VERSION

9       version 0.400000
10

SYNOPSIS

12           use Test::More;
13           use Plack::Test;
14           use HTTP::Request::Common; # install separately
15
16           use YourDancerApp;
17
18           my $app  = YourDancerApp->to_app;
19           my $test = Plack::Test->create($app);
20
21           my $res = $test->request( GET '/' );
22           is( $res->code, 200, '[GET /] Request successful' );
23           like( $res->content, qr/hello, world/, '[GET /] Correct content' );
24
25           done_testing;
26

DESCRIPTION

28       DEPRECATED. This module and all the functions listed below are
29       deprecated. Do not use this module. The routines provided by this
30       module for testing Dancer2 apps are buggy and unnecessary. Instead, use
31       the Plack::Test module as shown in the SYNOPSIS above and ignore the
32       functions in this documentation. Consult the Plack::Test documentation
33       for further details.
34
35       This module will be removed from the Dancer2 distribution in the near
36       future.  You should migrate all tests that use it over to the
37       Plack::Test module and remove this module from your system. This module
38       will throw warnings to remind you.
39
40       For now, you can silence the warnings by setting the "NO_WARN" option:
41
42           $Dancer::Test::NO_WARN = 1;
43
44       In the functions below, $test_name is always optional.
45

FUNCTIONS

47   dancer_response ($method, $path, $params, $arg_env);
48       Returns a Dancer2::Core::Response object for the given request.
49
50       Only $method and $path are required.
51
52       $params is a hashref with 'body' as a string; 'headers' can be an
53       arrayref or a HTTP::Headers object, 'files' can be arrayref of hashref,
54       containing some files to upload:
55
56           dancer_response($method, $path,
57               {
58                   params => $params,
59                   body => $body,
60                   headers => $headers,
61                   files => [ { filename => '/path/to/file', name => 'my_file' } ],
62               }
63           );
64
65       A good reason to use this function is for testing POST requests. Since
66       POST requests may not be idempotent, it is necessary to capture the
67       content and status in one shot. Calling the response_status_is and
68       response_content_is functions in succession would make two requests,
69       each of which could alter the state of the application and cause
70       Schrodinger's cat to die.
71
72           my $response = dancer_response POST => '/widgets';
73           is $response->status, 202, "response for POST /widgets is 202";
74           is $response->content, "Widget #1 has been scheduled for creation",
75               "response content looks good for first POST /widgets";
76
77           $response = dancer_response POST => '/widgets';
78           is $response->status, 202, "response for POST /widgets is 202";
79           is $response->content, "Widget #2 has been scheduled for creation",
80               "response content looks good for second POST /widgets";
81
82       It's possible to test file uploads:
83
84           post '/upload' => sub { return upload('image')->content };
85
86           $response = dancer_response(POST => '/upload', {files => [{name => 'image', filename => '/path/to/image.jpg'}]});
87
88       In addition, you can supply the file contents as the "data" key:
89
90           my $data  = 'A test string that will pretend to be file contents.';
91           $response = dancer_response(POST => '/upload', {
92               files => [{name => 'test', filename => "filename.ext", data => $data}]
93           });
94
95       You can also supply a hashref of headers:
96
97           headers => { 'Content-Type' => 'text/plain' }
98
99   response_status_is ($request, $expected, $test_name);
100       Asserts that Dancer2's response for the given request has a status
101       equal to the one given.
102
103           response_status_is [GET => '/'], 200, "response for GET / is 200";
104
105   route_exists([$method, $path], $test_name)
106       Asserts that the given request matches a route handler in Dancer2's
107       registry. If the route would have returned a 404, the route still
108       exists and this test will pass.
109
110       Note that because Dancer2 uses the default route handler
111       Dancer2::Handler::File to match files in the public folder when no
112       other route matches, this test will always pass.  You can disable the
113       default route handlers in the configs but you probably want
114       "response_status_is" in Dancer2::Test or "dancer_response" in
115       Dancer2::Test
116
117           route_exists [GET => '/'], "GET / is handled";
118
119   route_doesnt_exist([$method, $path], $test_name)
120       Asserts that the given request does not match any route handler in
121       Dancer2's registry.
122
123       Note that this test is likely to always fail as any route not matched
124       will be handled by the default route handler in Dancer2::Handler::File.
125       This can be disabled in the configs.
126
127           route_doesnt_exist [GET => '/bogus_path'], "GET /bogus_path is not handled";
128
129   response_status_isnt([$method, $path], $status, $test_name)
130       Asserts that the status of Dancer2's response is not equal to the one
131       given.
132
133           response_status_isnt [GET => '/'], 404, "response for GET / is not a 404";
134
135   response_content_is([$method, $path], $expected, $test_name)
136       Asserts that the response content is equal to the $expected string.
137
138        response_content_is [GET => '/'], "Hello, World",
139               "got expected response content for GET /";
140
141   response_content_isnt([$method, $path], $not_expected, $test_name)
142       Asserts that the response content is not equal to the $not_expected
143       string.
144
145           response_content_isnt [GET => '/'], "Hello, World",
146               "got expected response content for GET /";
147
148   response_content_like([$method, $path], $regexp, $test_name)
149       Asserts that the response content for the given request matches the
150       regexp given.
151
152           response_content_like [GET => '/'], qr/Hello, World/,
153               "response content looks good for GET /";
154
155   response_content_unlike([$method, $path], $regexp, $test_name)
156       Asserts that the response content for the given request does not match
157       the regexp given.
158
159           response_content_unlike [GET => '/'], qr/Page not found/,
160               "response content looks good for GET /";
161
162   response_content_is_deeply([$method, $path], $expected_struct, $test_name)
163       Similar to response_content_is(), except that if response content and
164       $expected_struct are references, it does a deep comparison walking each
165       data structure to see if they are equivalent.
166
167       If the two structures are different, it will display the place where
168       they start differing.
169
170           response_content_is_deeply [GET => '/complex_struct'],
171               { foo => 42, bar => 24},
172               "got expected response structure for GET /complex_struct";
173
174   response_is_file ($request, $test_name);
175   response_headers_are_deeply([$method, $path], $expected, $test_name)
176       Asserts that the response headers data structure equals the one given.
177
178           response_headers_are_deeply [GET => '/'], [ 'X-Powered-By' => 'Dancer2 1.150' ];
179
180   response_headers_include([$method, $path], $expected, $test_name)
181       Asserts that the response headers data structure includes some of the
182       defined ones.
183
184           response_headers_include [GET => '/'], [ 'Content-Type' => 'text/plain' ];
185
186   route_pod_coverage()
187       Returns a structure describing pod coverage in your apps
188
189       for one app like this:
190
191           package t::lib::TestPod;
192           use Dancer2;
193
194           =head1 NAME
195
196           TestPod
197
198           =head2 ROUTES
199
200           =over
201
202           =cut
203
204           =item get "/in_testpod"
205
206           testpod
207
208           =cut
209
210           get '/in_testpod' => sub {
211               return 'get in_testpod';
212           };
213
214           get '/hello' => sub {
215               return "hello world";
216           };
217
218           =item post '/in_testpod/*'
219
220           post in_testpod
221
222           =cut
223
224           post '/in_testpod/*' => sub {
225               return 'post in_testpod';
226           };
227
228           =back
229
230           =head2 SPECIALS
231
232           =head3 PUBLIC
233
234           =over
235
236           =item get "/me:id"
237
238           =cut
239
240           get "/me:id" => sub {
241               return "ME";
242           };
243
244           =back
245
246           =head3 PRIVAT
247
248           =over
249
250           =item post "/me:id"
251
252           post /me:id
253
254           =cut
255
256           post "/me:id" => sub {
257               return "ME";
258           };
259
260           =back
261
262           =cut
263
264           1;
265
266       route_pod_coverage;
267
268       would return something like:
269
270           {
271               't::lib::TestPod' => {
272                   'has_pod'             => 1,
273                   'routes'              => [
274                       "post /in_testpod/*",
275                       "post /me:id",
276                       "get /in_testpod",
277                       "get /hello",
278                       "get /me:id"
279                   ],
280                   'undocumented_routes' => [
281                       "get /hello"
282                   ]
283               }
284           }
285
286   is_pod_covered('is pod covered')
287       Asserts that your apps have pods for all routes
288
289           is_pod_covered 'is pod covered'
290
291       to avoid test failures, you should document all your routes with one of
292       the following: head1, head2,head3,head4, item.
293
294           ex:
295
296           =item get '/login'
297
298           route to login
299
300           =cut
301
302           if you use:
303
304           any '/myaction' => sub {
305               # code
306           }
307
308           or
309
310           any ['get', 'post'] => '/myaction' => sub {
311               # code
312           };
313
314           you need to create pods for each one of the routes created there.
315
316   import
317       When Dancer2::Test is imported, it should be passed all the
318       applications that are supposed to be tested.
319
320       If none passed, then the caller is supposed to be the sole application
321       to test.
322
323           # t/sometest.t
324
325           use t::lib::Foo;
326           use t::lib::Bar;
327
328           use Dancer2::Test apps => ['t::lib::Foo', 't::lib::Bar'];
329

AUTHOR

331       Dancer Core Developers
332
334       This software is copyright (c) 2022 by Alexis Sukrieh.
335
336       This is free software; you can redistribute it and/or modify it under
337       the same terms as the Perl 5 programming language system itself.
338
339
340
341perl v5.36.0                      2022-07-22                  Dancer2::Test(3)
Impressum