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