File Coverage

blib/lib/Test/WWW/Mechanize/PSGI.pm
Criterion Covered Total %
statement 46 46 100.0
branch 6 8 75.0
condition 1 3 33.3
subroutine 11 11 100.0
pod 2 2 100.0
total 66 70 94.2


line stmt bran cond sub pod time code
1             package Test::WWW::Mechanize::PSGI;
2             $Test::WWW::Mechanize::PSGI::VERSION = '0.37';
3 2     2   30267 use strict;
  2         4  
  2         48  
4 2     2   9 use warnings;
  2         4  
  2         51  
5              
6 2     2   11 use Carp;
  2         3  
  2         144  
7 2     2   745 use HTTP::Message::PSGI;
  2         36818  
  2         96  
8 2     2   966 use Test::WWW::Mechanize;
  2         255759  
  2         103  
9 2     2   20 use Try::Tiny;
  2         6  
  2         139  
10              
11 2     2   13 use base 'Test::WWW::Mechanize';
  2         6  
  2         844  
12              
13             my $Test = Test::Builder->new();
14              
15             sub new {
16 4     4 1 15081 my $class = shift;
17 4         16 my %args = @_;
18              
19             # Dont let LWP complain about options for our attributes
20 4         11 my $app = $args{app};
21 4         11 delete $args{app};
22 4 50       16 confess('Missing argument app') unless $app;
23 4 50 33     37 confess('Argument app should be a code reference')
24             unless ref($app) && ref($app) eq 'CODE';
25              
26 4         38 my $self = $class->SUPER::new(%args);
27 4         22811 $self->{app} = $app;
28 4         15 return $self;
29             }
30              
31             sub simple_request {
32 5     5 1 21952 my ( $self, $request ) = @_;
33              
34 5         35 $self->run_handlers( "request_send", $request );
35              
36 5         104 my $uri = $request->uri;
37 5 100       60 $uri->scheme('http') unless defined $uri->scheme;
38 5 100       4986 $uri->host('localhost') unless defined $uri->host;
39              
40 5         562 my $env = $self->prepare_request($request)->to_psgi;
41 5         8013 my $response;
42             try {
43 5     5   246 $response = HTTP::Response->from_psgi( $self->{app}->($env) );
44             }
45             catch {
46 1     1   30 $Test->diag("PSGI error: $_");
47 1         193 $response = HTTP::Response->new(500);
48 1         54 $response->content($_);
49 1         28 $response->content_type('');
50 5         52 };
51 5         1348 $response->request($request);
52 5         65 $self->run_handlers( "response_done", $response );
53 5         1665 return $response;
54             }
55              
56             1;
57              
58             =pod
59              
60             =encoding UTF-8
61              
62             =head1 NAME
63              
64             Test::WWW::Mechanize::PSGI - Test PSGI programs using WWW::Mechanize
65              
66             =head1 VERSION
67              
68             version 0.37
69              
70             =head1 SYNOPSIS
71              
72             # We're in a t/*.t test script...
73             use Test::WWW::Mechanize::PSGI;
74              
75             my $mech = Test::WWW::Mechanize::PSGI->new(
76             app => sub {
77             my $env = shift;
78             return [
79             200,
80             [ 'Content-Type' => 'text/html' ],
81             [ 'HiHello World'
82             ]
83             ];
84             },
85             );
86             $mech->get_ok('/');
87             is( $mech->ct, 'text/html', 'Is text/html' );
88             $mech->title_is('Hi');
89             $mech->content_contains('Hello World');
90             # ... and all other Test::WWW::Mechanize methods
91              
92             =head1 DESCRIPTION
93              
94             L is a specification to decouple web server environments from
95             web application framework code. L is a subclass
96             of L that incorporates features for web application
97             testing. The L module meshes the two to
98             allow easy testing of L applications.
99              
100             Testing web applications has always been a bit tricky, normally
101             requiring starting a web server for your application and making real HTTP
102             requests to it. This module allows you to test L web
103             applications but does not require a server or issue HTTP
104             requests. Instead, it passes the HTTP request object directly to
105             L. Thus you do not need to use a real hostname:
106             "http://localhost/" will do. However, this is optional. The following
107             two lines of code do exactly the same thing:
108              
109             $mech->get_ok('/action');
110             $mech->get_ok('http://localhost/action');
111              
112             This makes testing fast and easy. L provides
113             functions for common web testing scenarios. For example:
114              
115             $mech->get_ok( $page );
116             $mech->title_is( "Invoice Status", "Make sure we're on the invoice page" );
117             $mech->content_contains( "Andy Lester", "My name somewhere" );
118             $mech->content_like( qr/(cpan|perl)\.org/, "Link to perl.org or CPAN" );
119              
120             An alternative to this module is L.
121              
122             =head1 CONSTRUCTOR
123              
124             =head2 new
125              
126             Behaves like, and calls, L's C method. You should pass
127             in your application:
128              
129             my $mech = Test::WWW::Mechanize::PSGI->new(
130             app => sub {
131             my $env = shift;
132             return [ 200, [ 'Content-Type' => 'text/plain' ], ['Hello World'] ],;
133             },
134             );
135              
136             =head1 METHODS: HTTP VERBS
137              
138             =head2 $mech->get_ok($url, [ \%LWP_options ,] $desc)
139              
140             A wrapper around WWW::Mechanize's get(), with similar options, except
141             the second argument needs to be a hash reference, not a hash. Like
142             well-behaved C<*_ok()> functions, it returns true if the test passed,
143             or false if not.
144              
145             A default description of "GET $url" is used if none if provided.
146              
147             =head2 $mech->head_ok($url, [ \%LWP_options ,] $desc)
148              
149             A wrapper around WWW::Mechanize's head(), with similar options, except
150             the second argument needs to be a hash reference, not a hash. Like
151             well-behaved C<*_ok()> functions, it returns true if the test passed,
152             or false if not.
153              
154             A default description of "HEAD $url" is used if none if provided.
155              
156             =head2 $mech->post_ok( $url, [ \%LWP_options ,] $desc )
157              
158             A wrapper around WWW::Mechanize's post(), with similar options, except
159             the second argument needs to be a hash reference, not a hash. Like
160             well-behaved C<*_ok()> functions, it returns true if the test passed,
161             or false if not.
162              
163             A default description of "POST to $url" is used if none if provided.
164              
165             =head2 $mech->put_ok( $url, [ \%LWP_options ,] $desc )
166              
167             A wrapper around WWW::Mechanize's put(), with similar options, except
168             the second argument needs to be a hash reference, not a hash. Like
169             well-behaved C<*_ok()> functions, it returns true if the test passed,
170             or false if not.
171              
172             A default description of "PUT to $url" is used if none if provided.
173              
174             =head2 $mech->submit_form_ok( \%params [, $desc] )
175              
176             Makes a C call and executes tests on the results.
177             The form must be found, and then submitted successfully. Otherwise,
178             this test fails.
179              
180             I<%params> is a hashref containing the params to pass to C.
181             Note that the params to C are a hash whereas the params to
182             this function are a hashref. You have to call this function like:
183              
184             $agent->submit_form_ok({
185             form_number => 3,
186             fields => {
187             username => 'mungo',
188             password => 'lost-and-alone',
189             }
190             }, "looking for 3rd form" );
191              
192             As with other test functions, C<$desc> is optional. If it is supplied
193             then it will display when running the test harness in verbose mode.
194              
195             Returns true value if the specified link was found and followed
196             successfully. The L object returned by submit_form()
197             is not available.
198              
199             =head2 $mech->follow_link_ok( \%params [, $desc] )
200              
201             Makes a C call and executes tests on the results.
202             The link must be found, and then followed successfully. Otherwise,
203             this test fails.
204              
205             I<%params> is a hashref containing the params to pass to C.
206             Note that the params to C are a hash whereas the params to
207             this function are a hashref. You have to call this function like:
208              
209             $mech->follow_link_ok( {n=>3}, "looking for 3rd link" );
210              
211             As with other test functions, C<$desc> is optional. If it is supplied
212             then it will display when running the test harness in verbose mode.
213              
214             Returns a true value if the specified link was found and followed
215             successfully. The L object returned by follow_link()
216             is not available.
217              
218             =head2 click_ok( $button[, $desc] )
219              
220             Clicks the button named by C<$button>. An optional C<$desc> can
221             be given for the test.
222              
223             =head1 METHODS: CONTENT CHECKING
224              
225             =head2 $mech->html_lint_ok( [$desc] )
226              
227             Checks the validity of the HTML on the current page. If the page is not
228             HTML, then it fails. The URI is automatically appended to the I<$desc>.
229              
230             Note that HTML::Lint must be installed for this to work. Otherwise,
231             it will blow up.
232              
233             =head2 $mech->title_is( $str [, $desc ] )
234              
235             Tells if the title of the page is the given string.
236              
237             $mech->title_is( "Invoice Summary" );
238              
239             =head2 $mech->title_like( $regex [, $desc ] )
240              
241             Tells if the title of the page matches the given regex.
242              
243             $mech->title_like( qr/Invoices for (.+)/
244              
245             =head2 $mech->title_unlike( $regex [, $desc ] )
246              
247             Tells if the title of the page matches the given regex.
248              
249             $mech->title_unlike( qr/Invoices for (.+)/
250              
251             =head2 $mech->base_is( $str [, $desc ] )
252              
253             Tells if the base of the page is the given string.
254              
255             $mech->base_is( "http://example.com/" );
256              
257             =head2 $mech->base_like( $regex [, $desc ] )
258              
259             Tells if the base of the page matches the given regex.
260              
261             $mech->base_like( qr{http://example.com/index.php?PHPSESSID=(.+)});
262              
263             =head2 $mech->base_unlike( $regex [, $desc ] )
264              
265             Tells if the base of the page matches the given regex.
266              
267             $mech->base_unlike( qr{http://example.com/index.php?PHPSESSID=(.+)});
268              
269             =head2 $mech->content_is( $str [, $desc ] )
270              
271             Tells if the content of the page matches the given string
272              
273             =head2 $mech->content_contains( $str [, $desc ] )
274              
275             Tells if the content of the page contains I<$str>.
276              
277             =head2 $mech->content_lacks( $str [, $desc ] )
278              
279             Tells if the content of the page lacks I<$str>.
280              
281             =head2 $mech->content_like( $regex [, $desc ] )
282              
283             Tells if the content of the page matches I<$regex>.
284              
285             =head2 $mech->content_unlike( $regex [, $desc ] )
286              
287             Tells if the content of the page does NOT match I<$regex>.
288              
289             =head2 $mech->has_tag( $tag, $text [, $desc ] )
290              
291             Tells if the page has a C<$tag> tag with the given content in its text.
292              
293             =head2 $mech->has_tag_like( $tag, $regex [, $desc ] )
294              
295             Tells if the page has a C<$tag> tag with the given content in its text.
296              
297             =head2 $mech->followable_links()
298              
299             Returns a list of links that L can follow. This is only http
300             and https links.
301              
302             =head2 $mech->page_links_ok( [ $desc ] )
303              
304             Follow all links on the current page and test for HTTP status 200
305              
306             $mech->page_links_ok('Check all links');
307              
308             =head2 $mech->page_links_content_like( $regex [, $desc ] )
309              
310             Follow all links on the current page and test their contents for I<$regex>.
311              
312             $mech->page_links_content_like( qr/foo/,
313             'Check all links contain "foo"' );
314              
315             =head2 $mech->links_ok( $links [, $desc ] )
316              
317             Follow specified links on the current page and test for HTTP status
318             200. The links may be specified as a reference to an array containing
319             L objects, an array of URLs, or a scalar URL
320             name.
321              
322             my @links = $mech->find_all_links( url_regex => qr/cnn\.com$/ );
323             $mech->links_ok( \@links, 'Check all links for cnn.com' );
324              
325             my @links = qw( index.html search.html about.html );
326             $mech->links_ok( \@links, 'Check main links' );
327              
328             $mech->links_ok( 'index.html', 'Check link to index' );
329              
330             =head2 $mech->link_status_is( $links, $status [, $desc ] )
331              
332             Follow specified links on the current page and test for HTTP status
333             passed. The links may be specified as a reference to an array
334             containing L objects, an array of URLs, or a
335             scalar URL name.
336              
337             my @links = $mech->followable_links();
338             $mech->link_status_is( \@links, 403,
339             'Check all links are restricted' );
340              
341             =head2 $mech->link_status_isnt( $links, $status [, $desc ] )
342              
343             Follow specified links on the current page and test for HTTP status
344             passed. The links may be specified as a reference to an array
345             containing L objects, an array of URLs, or a
346             scalar URL name.
347              
348             my @links = $mech->followable_links();
349             $mech->link_status_isnt( \@links, 404,
350             'Check all links are not 404' );
351              
352             =head2 $mech->link_content_like( $links, $regex [, $desc ] )
353              
354             Follow specified links on the current page and test the resulting
355             content of each against I<$regex>. The links may be specified as a
356             reference to an array containing L objects, an
357             array of URLs, or a scalar URL name.
358              
359             my @links = $mech->followable_links();
360             $mech->link_content_like( \@links, qr/Restricted/,
361             'Check all links are restricted' );
362              
363             =head2 $mech->link_content_unlike( $links, $regex [, $desc ] )
364              
365             Follow specified links on the current page and test that the resulting
366             content of each does not match I<$regex>. The links may be specified as a
367             reference to an array containing L objects, an array
368             of URLs, or a scalar URL name.
369              
370             my @links = $mech->followable_links();
371             $mech->link_content_unlike( \@links, qr/Restricted/,
372             'No restricted links' );
373              
374             =head2 $mech->stuff_inputs( [\%options] )
375              
376             Finds all free-text input fields (text, textarea, and password) in the
377             current form and fills them to their maximum length in hopes of finding
378             application code that can't handle it. Fields with no maximum length
379             and all textarea fields are set to 66000 bytes, which will often be
380             enough to overflow the data's eventual receptacle.
381              
382             There is no return value.
383              
384             If there is no current form then nothing is done.
385              
386             The hashref $options can contain the following keys:
387              
388             =over
389              
390             =item * ignore
391              
392             hash value is arrayref of field names to not touch, e.g.:
393              
394             $mech->stuff_inputs( {
395             ignore => [qw( specialfield1 specialfield2 )],
396             } );
397              
398             =item * fill
399              
400             hash value is default string to use when stuffing fields. Copies
401             of the string are repeated up to the max length of each field. E.g.:
402              
403             $mech->stuff_inputs( {
404             fill => '@' # stuff all fields with something easy to recognize
405             } );
406              
407             =item * specs
408              
409             hash value is arrayref of hashrefs with which you can pass detailed
410             instructions about how to stuff a given field. E.g.:
411              
412             $mech->stuff_inputs( {
413             specs=>{
414             # Some fields are datatype-constrained. It's most common to
415             # want the field stuffed with valid data.
416             widget_quantity => { fill=>'9' },
417             notes => { maxlength=>2000 },
418             }
419             } );
420              
421             The specs allowed are I (use this fill for the field rather than
422             the default) and I (use this as the field's maxlength instead
423             of any maxlength specified in the HTML).
424              
425             =back
426              
427             =head1 AUTHOR
428              
429             Leon Brocard
430              
431             =head1 COPYRIGHT AND LICENSE
432              
433             This software is copyright (c) 2009 by Leon Brocard.
434              
435             This is free software; you can redistribute it and/or modify it under
436             the same terms as the Perl 5 programming language system itself.
437              
438             =cut
439              
440             __END__