File Coverage

t/base.t
Criterion Covered Total %
statement n/a
branch n/a
condition n/a
subroutine n/a
pod n/a
total n/a


line stmt bran cond sub pod time code
1             use v5.40;
2             use Test2::V1 -ipP;
3             use Test2::Thunderhorse;
4             use HTTP::Request::Common;
5             use Path::Tiny qw(cwd);
6              
7             use Future::AsyncAwait;
8              
9             ################################################################################
10             # This tests whether Thunderhorse basic app works
11             ################################################################################
12              
13             package BasicApp {
14             use Mooish::Base -standard;
15              
16             use Gears::X::HTTP;
17              
18             extends 'Thunderhorse::App';
19              
20             sub build ($self)
21             {
22             my $router = $self->router;
23              
24             $router->add(
25             '/foundation/:ph' => {
26             to => sub ($self, $ctx, $ph) {
27             my $self_class = ref $self;
28             my $ctx_class = ref $ctx;
29              
30             return "$self_class;$ctx_class;$ph";
31             }
32             }
33             );
34              
35             $router->add(
36             '/send' => {
37             to => sub ($self, $ctx) {
38             $ctx->res->text('this gets rendered');
39             return 'this does not get rendered';
40             }
41             }
42             );
43              
44             $router->add(
45             '/preset_headers/?ex_code' => {
46             to => sub ($self, $ctx, $code) {
47             $ctx->res->status(201)->content_type('application/xml');
48             Gears::X::HTTP->raise($code, 'test')
49             if $code;
50              
51             return 'this gets rendered as xml';
52             }
53             }
54             );
55              
56             $router->add(
57             '/error' => {
58             to => sub {
59             die 'error occured';
60             }
61             }
62             );
63              
64             my $bridge = $router->add(
65             '/bridge/:must_be_zero' => {
66             to => sub ($self, $ctx, $must_be_zero) {
67             Gears::X::HTTP->raise(
68             403 => 'this exception renders 403, but this message is private in production'
69             ) unless $must_be_zero eq '0';
70              
71             return undef;
72             }
73             }
74             );
75              
76             $bridge->add(
77             '/success' => {
78             to => sub ($self, $ctx, $) {
79             return 'bridge passed';
80             },
81             }
82             );
83              
84             my $bridge_unimplemented = $router->add('/bridge2');
85              
86             $bridge_unimplemented->add(
87             '/success' => {
88             to => sub ($self, $ctx) {
89             return 'bridge passed';
90             },
91             },
92             );
93             }
94             };
95              
96             package BasicAppProd {
97             use Mooish::Base -standard;
98              
99             extends 'BasicApp';
100              
101             sub is_production { true }
102              
103             sub build ($self)
104             {
105             $self->SUPER::build;
106             }
107             }
108              
109             my $app = BasicApp->new;
110             my $app_prod = BasicAppProd->new;
111              
112             is $app->path->stringify, cwd->child('t')->stringify, 'application path ok';
113              
114             subtest 'should route to a valid location' => sub {
115             http $app, GET '/foundation/placeholder';
116             http_status_is 200;
117             http_header_is 'content-type', 'text/html; charset=utf-8';
118             http_text_is 'Thunderhorse::AppController;Thunderhorse::Context::Facade;placeholder';
119             };
120              
121             subtest 'should route to 404' => sub {
122             http $app, GET '/foundation';
123             http_status_is 404;
124             http_header_is 'Content-Type', 'text/plain; charset=utf-8';
125             http_text_is 'Not Found';
126             };
127              
128             subtest 'should render text set by res->text' => sub {
129             http $app, GET '/send';
130             http_status_is 200;
131             http_header_is 'Content-Type', 'text/plain; charset=utf-8';
132             http_text_is 'this gets rendered';
133             };
134              
135             subtest 'should render without overriding set headers' => sub {
136             http $app, GET '/preset_headers';
137             http_status_is 201;
138             http_header_is 'content-type', 'application/xml; charset=utf-8';
139             http_text_is 'this gets rendered as xml';
140             };
141              
142             subtest 'should override headers when an exception is thrown' => sub {
143             http $app, GET '/preset_headers/403';
144             http_status_is 403;
145             http_header_is 'content-type', 'text/plain; charset=utf-8';
146             like http->text, qr{\Q[HTTP] 403 - test\E}, 'text ok';
147              
148             http $app_prod, GET '/preset_headers/403';
149             http_status_is 403;
150             http_header_is 'content-type', 'text/plain; charset=utf-8';
151             http_text_is 'Forbidden';
152             };
153              
154             subtest 'should pass bridge and reach success route' => sub {
155             http $app, GET '/bridge/0/success';
156             http_status_is 200;
157             http_header_is 'Content-Type', 'text/html; charset=utf-8';
158             http_text_is 'bridge passed';
159             };
160              
161             subtest 'should fail bridge and return 403' => sub {
162             http $app, GET '/bridge/1/success';
163             http_status_is 403;
164             http_header_is 'Content-Type', 'text/plain; charset=utf-8';
165             like http->text, qr{\Q[HTTP] 403 - this exception renders 403, but this message is private in production\E},
166             'text ok';
167              
168             http $app_prod, GET '/bridge/1/success';
169             http_status_is 403;
170             http_header_is 'content-type', 'text/plain; charset=utf-8';
171             http_text_is 'Forbidden';
172             };
173              
174             subtest 'should pass unimplemented bridge' => sub {
175             http $app, GET '/bridge2/success';
176             http_status_is 200;
177             http_header_is 'Content-Type', 'text/html; charset=utf-8';
178             http_text_is 'bridge passed';
179             };
180              
181             subtest 'should not render errors' => sub {
182             http $app, GET '/error';
183             http_status_is 500;
184             http_header_is 'Content-Type', 'text/plain; charset=utf-8';
185             like http->text, qr{\Qerror occured\E}, 'error ok';
186              
187             http $app_prod, GET '/error';
188             http_status_is 500;
189             http_header_is 'Content-Type', 'text/plain; charset=utf-8';
190             http_text_is 'Internal Server Error';
191             };
192              
193             done_testing;
194