fix a memory leak introduced by 1f8cad5e5a1875de94d63ac91d8ded4d2282c62e
[catagits/Web-Simple.git] / t / dispatch_misc.t
1 use strict;
2 use warnings FATAL => 'all';
3 no warnings::illegalproto;
4
5 use Test::More;
6
7 use HTTP::Request::Common qw(GET POST);
8 use Web::Dispatch;
9 use HTTP::Response;
10 use Web::Dispatch::Predicates 'match_true';
11
12 my @dispatch;
13
14 {
15     use Web::Simple 'MiscTest';
16
17     package MiscTest;
18     sub dispatch_request { @dispatch }
19     sub string_method { [ 999, [], [""] ]; }
20 }
21
22 my $app = MiscTest->new;
23 sub run_request { $app->run_test_request( @_ ); }
24
25 string_method_name();
26 app_is_non_plack();
27 app_is_object();
28 app_is_just_sub();
29 plack_app_return();
30 broken_route_def();
31 invalid_psgi_responses();
32 middleware_as_only_route();
33 route_returns_middleware_plus_extra();
34 route_returns_undef();
35 matcher_nonsub_pair();
36
37 done_testing();
38
39 sub string_method_name {
40     @dispatch = ( '/' => "string_method" );
41
42     my $get = run_request( GET => 'http://localhost/' );
43
44     cmp_ok $get->code, '==', 999, "a dispatcher that's a string matching a method on the dispatch object gets executed";
45 }
46
47 sub app_is_non_plack {
48
49     my $r = HTTP::Response->new( 999 );
50
51     my $d = Web::Dispatch->new( dispatch_app => $r );
52     eval { $d->call };
53
54     like $@, qr/No idea how we got here with HTTP::Response/,
55       "Web::Dispatch dies when run with an app() that is a non-PSGI object";
56     undef $@;
57 }
58
59 sub app_is_object {
60     {
61
62         package ObjectApp;
63         use Moo;
64         sub to_app { [ 999, [], ["ok"] ] }
65     }
66
67     my $o = ObjectApp->new;
68     my $d = Web::Dispatch->new( dispatch_object => $o );
69     my $res = $d->call;
70
71     cmp_ok $res->[0], '==', 999, "Web::Dispatch can dispatch properly, given only an object with to_app method";
72 }
73
74 sub app_is_just_sub {
75     my $d = Web::Dispatch->new( dispatch_app => sub () { [ 999, [], ["ok"] ] } );
76     my $res = $d->call( {} );
77
78     cmp_ok $res->[0], '==', 999,
79       "Web::Dispatch can dispatch properly, given only an app that's just a sub, with no object involved";
80 }
81
82 sub plack_app_return {
83     {
84
85         package FauxPlackApp;
86         sub new { bless {}, $_[0] }
87
88         sub to_app {
89             return sub {
90                 [ 999, [], [""] ];
91             };
92         }
93     }
94
95     @dispatch = (
96         sub (/) {
97             FauxPlackApp->new;
98         }
99     );
100
101     my $get = run_request( GET => 'http://localhost/' );
102
103     cmp_ok $get->code, '==', 999,
104       "when a route returns a thing that look like a Plack app, the web app redispatches to that thing";
105 }
106
107 sub broken_route_def {
108
109     @dispatch = ( '/' => "" );
110
111     my $get = run_request( GET => 'http://localhost/' );
112
113     cmp_ok $get->code, '==', 500, "a route definition by hash that doesn't pair a sub with a route dies";
114     like $get->content, qr[No idea how we got here with /], "the error message points out the broken definition";
115 }
116
117 sub invalid_psgi_responses {
118     undef $@;
119
120     my @responses = (
121         [ [ sub { } ], "an arrayref with a single sub in it" ],
122         [ ["moo"], "an arrayref with a scalar that is not a sub" ],
123         [ bless( {}, "FauxObject" ), "an object without to_app method" ],
124     );
125
126     for my $response ( @responses ) {
127         @dispatch = ( sub (/) { $response->[0] } );
128
129         eval { run_request( GET => 'http://localhost/' ) };
130
131         like $@, qr/Can't call method "request" on an undefined value .*MockHTTP/,
132           sprintf(
133             "if a route returns %s, then that is returned as a response by WD, causing HTTP::Message::PSGI to choke",
134             $response->[1] );
135         undef $@;
136     }
137 }
138
139 sub middleware_as_only_route {
140     @dispatch = ( bless {}, "Plack::Middleware" );
141
142     my $get = run_request( GET => 'http://localhost/' );
143
144     cmp_ok $get->code, '==', 500, "a route definition consisting of only a middleware causes a bail";
145     like $get->content, qr[Multiple results but first one is a middleware \(Plack::Middleware=],
146       "the error message mentions the middleware class";
147 }
148
149 sub route_returns_middleware_plus_extra {
150     @dispatch = (
151         sub (/) {
152             return ( bless( {}, "Plack::Middleware" ), "" );
153         }
154     );
155
156     my $get = run_request( GET => 'http://localhost/' );
157
158     cmp_ok $get->code, '==', 500, "a route returning a middleware and at least one other variable causes a bail";
159     like $get->content,
160       qr[Multiple results but first one is a middleware \(Plack::Middleware=],
161       "the error message mentions the middleware class";
162 }
163
164 sub route_returns_undef {
165     @dispatch = (
166         sub (/) {
167             (
168                 sub(/) {
169                     undef;
170                 },
171                 sub(/) {
172                     [ 900, [], [""] ];
173                 }
174             );
175         },
176         sub () {
177             [ 400, [], [""] ];
178         }
179     );
180
181     my $get = run_request( GET => 'http://localhost/' );
182
183     cmp_ok $get->code, '==', 900, "a route that returns undef causes WD to ignore it and resume dispatching";
184 }
185
186 sub matcher_nonsub_pair {
187     @dispatch = ( match_true() => 5 );
188
189     my $get = run_request( GET => 'http://localhost/' );
190
191     cmp_ok $get->code, '==', 500, "a route definition that pairs a WD::Matcher a non-sub dies";
192     like $get->content, qr[No idea how we got here with Web::Dispatch::M],
193       "the error message points out the broken definition";
194 }