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