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