line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Kelp::Less; |
2
|
|
|
|
|
|
|
|
3
|
2
|
|
|
2
|
|
2426
|
use Kelp; |
|
2
|
|
|
|
|
6
|
|
|
2
|
|
|
|
|
17
|
|
4
|
2
|
|
|
2
|
|
15
|
use Kelp::Base -strict; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
8
|
|
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
our @EXPORT = qw/ |
7
|
|
|
|
|
|
|
app |
8
|
|
|
|
|
|
|
attr |
9
|
|
|
|
|
|
|
config |
10
|
|
|
|
|
|
|
del |
11
|
|
|
|
|
|
|
debug |
12
|
|
|
|
|
|
|
error |
13
|
|
|
|
|
|
|
get |
14
|
|
|
|
|
|
|
module |
15
|
|
|
|
|
|
|
named |
16
|
|
|
|
|
|
|
param |
17
|
|
|
|
|
|
|
post |
18
|
|
|
|
|
|
|
put |
19
|
|
|
|
|
|
|
req |
20
|
|
|
|
|
|
|
res |
21
|
|
|
|
|
|
|
route |
22
|
|
|
|
|
|
|
run |
23
|
|
|
|
|
|
|
session |
24
|
|
|
|
|
|
|
stash |
25
|
|
|
|
|
|
|
template |
26
|
|
|
|
|
|
|
view |
27
|
|
|
|
|
|
|
/; |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
our $app; |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
sub import { |
32
|
2
|
|
|
2
|
|
13
|
my $class = shift; |
33
|
2
|
|
|
|
|
5
|
my $caller = caller; |
34
|
2
|
|
|
2
|
|
301
|
no strict 'refs'; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
1692
|
|
35
|
2
|
|
|
|
|
6
|
for my $sub (@EXPORT) { |
36
|
40
|
|
|
|
|
1674
|
*{"${caller}::$sub"} = eval("\\\&$sub"); |
|
40
|
|
|
|
|
285
|
|
37
|
|
|
|
|
|
|
} |
38
|
|
|
|
|
|
|
|
39
|
2
|
|
|
|
|
13
|
strict->import; |
40
|
2
|
|
|
|
|
17
|
warnings->import; |
41
|
2
|
|
|
|
|
99
|
feature->import(':5.10'); |
42
|
|
|
|
|
|
|
|
43
|
2
|
|
|
|
|
10
|
$app = Kelp->new(config_module => 'Config::Less', @_); |
44
|
2
|
|
|
|
|
7
|
$app->routes->base('main'); |
45
|
|
|
|
|
|
|
} |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
sub route { |
48
|
17
|
|
|
17
|
1
|
88
|
my ( $path, $to ) = @_; |
49
|
17
|
|
|
|
|
59
|
$app->add_route( $path, $to ); |
50
|
|
|
|
|
|
|
} |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
sub get { |
53
|
2
|
|
|
2
|
1
|
16
|
my ( $path, $to ) = @_; |
54
|
2
|
50
|
|
|
|
13
|
route ref($path) ? $path : [ GET => $path ], $to; |
55
|
|
|
|
|
|
|
} |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
sub post { |
58
|
1
|
|
|
1
|
1
|
4
|
my ( $path, $to ) = @_; |
59
|
1
|
50
|
|
|
|
5
|
route ref($path) ? $path : [ POST => $path ], $to; |
60
|
|
|
|
|
|
|
} |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
sub put { |
63
|
1
|
|
|
1
|
1
|
4
|
my ( $path, $to ) = @_; |
64
|
1
|
50
|
|
|
|
6
|
route ref($path) ? $path : [ PUT => $path ], $to; |
65
|
|
|
|
|
|
|
} |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
sub del { |
68
|
1
|
|
|
1
|
1
|
3
|
my ( $path, $to ) = @_; |
69
|
1
|
50
|
|
|
|
9
|
route ref($path) ? $path : [ DELETE => $path ], $to; |
70
|
|
|
|
|
|
|
} |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
sub run { |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
# If we're running a test, then return the entire app, |
75
|
|
|
|
|
|
|
# otherwise return the PSGI subroutine |
76
|
1
|
50
|
|
1
|
1
|
51
|
return $ENV{KELP_TESTING} ? $app : $app->run; |
77
|
|
|
|
|
|
|
} |
78
|
|
|
|
|
|
|
|
79
|
3
|
|
|
3
|
1
|
24
|
sub app { $app } |
80
|
2
|
|
|
2
|
1
|
15
|
sub attr { Kelp::Base::attr( ref($app), @_ ) } |
81
|
2
|
|
|
2
|
1
|
16
|
sub param { $app->param(@_) } |
82
|
0
|
|
|
0
|
0
|
0
|
sub session { $app->session(@_) } |
83
|
2
|
|
|
2
|
1
|
14
|
sub stash { $app->stash(@_) } |
84
|
1
|
|
|
1
|
1
|
8
|
sub named { $app->named(@_) } |
85
|
1
|
|
|
1
|
1
|
11
|
sub req { $app->req } |
86
|
1
|
|
|
1
|
1
|
7
|
sub res { $app->res } |
87
|
1
|
|
|
1
|
1
|
11
|
sub template { $app->res->template(@_) } |
88
|
0
|
|
|
0
|
1
|
0
|
sub view { $app->res->template(@_) } |
89
|
0
|
0
|
|
0
|
0
|
0
|
sub debug { $app->debug(@_) if $app->can('debug') } |
90
|
0
|
0
|
|
0
|
0
|
0
|
sub error { $app->error(@_) if $app->can('error') } |
91
|
2
|
|
|
2
|
1
|
118
|
sub module { $app->load_module(@_) } |
92
|
1
|
|
|
1
|
1
|
9
|
sub config { $app->config(@_) } |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
1; |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
__END__ |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
=pod |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
=head1 NAME |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
Kelp::Less - Quick prototyping with Kelp |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
=head1 SYNOPSIS |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
use Kelp::Less; |
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
get '/person/:name' => sub { |
109
|
|
|
|
|
|
|
"Hello " . named 'name'; |
110
|
|
|
|
|
|
|
}; |
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
run; |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
=head1 DESCRIPTION |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
This class exists to provide a way for quick and sloppy prototyping of a web |
117
|
|
|
|
|
|
|
application. It is a wrapper for L<Kelp>, which imports several keywords, making |
118
|
|
|
|
|
|
|
it easier and less verbose to create a quick web app. |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
It's called C<Less>, because there is less typing involved, and |
121
|
|
|
|
|
|
|
because it is suited for smaller, less complicated web projects. We encourage |
122
|
|
|
|
|
|
|
you to use it anywhere you see fit, however for mid-size and big applications we |
123
|
|
|
|
|
|
|
recommend that you use the fully structured L<Kelp>. This way you can take |
124
|
|
|
|
|
|
|
advantage of its powerful router, initialization and testing capabilities. |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
=head1 QUICK START |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
Each web app begins with C<use Kelp::Less;>. This automatically imports C<strict>, |
129
|
|
|
|
|
|
|
C<warnings>, C<v5.10> as well as several useful functions. You can pass any |
130
|
|
|
|
|
|
|
parameters to the constructor at the C<use> statement: |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
use Kelp::Less mode => 'development'; |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
The above is equivalent to: |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
use Kelp; |
137
|
|
|
|
|
|
|
my $app = Kelp->new( mode => 'development' ); |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
After that, you could add any initializations and attributes. For example, connect |
140
|
|
|
|
|
|
|
to a database or setup cache. C<Kelp::Less> exports L<attr|Kelp::Base/attr>, |
141
|
|
|
|
|
|
|
so you can use it to register attributes to your app. |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
# Connect to DBI and CHI right away |
144
|
|
|
|
|
|
|
attr dbh => sub { |
145
|
|
|
|
|
|
|
DBI->connect( @{ app->config('database') } ); |
146
|
|
|
|
|
|
|
}; |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
attr cache => sub { |
149
|
|
|
|
|
|
|
CHI->new( @{ app->config('cache') } ); |
150
|
|
|
|
|
|
|
}; |
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
# Another lazy attribute. |
153
|
|
|
|
|
|
|
attr version => sub { |
154
|
|
|
|
|
|
|
app->dbh->selectrow_array("SELECT version FROM vars"); |
155
|
|
|
|
|
|
|
}; |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
# Later: |
158
|
|
|
|
|
|
|
app->dbh->do(...); |
159
|
|
|
|
|
|
|
app->cache->get(...); |
160
|
|
|
|
|
|
|
if ( app->version ) { ... } |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
Now is a good time to add routes. Routes are added via the L</route> keyword and |
163
|
|
|
|
|
|
|
they are automatically registered in your app. A route needs two parameters - |
164
|
|
|
|
|
|
|
C<path> and C<destination>. These are exactly equivalent to L<Kelp::Routes/add>, |
165
|
|
|
|
|
|
|
and you are encouraged to read its POD to get familiar with how to define routes. |
166
|
|
|
|
|
|
|
Here are a few examples for the impatient: |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
# Add a 'catch-all-methods' route and send it to an anonymous sub |
169
|
|
|
|
|
|
|
route '/hello/:name' => sub { |
170
|
|
|
|
|
|
|
return "Hello " . named('name'); |
171
|
|
|
|
|
|
|
}; |
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
# Add a POST route |
174
|
|
|
|
|
|
|
route [ POST => '/edit/:id' ] => sub { |
175
|
|
|
|
|
|
|
# Do something with named('id') |
176
|
|
|
|
|
|
|
}; |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
# Route that runs an existing sub in your code |
179
|
|
|
|
|
|
|
route '/login' => 'login'; |
180
|
|
|
|
|
|
|
sub login { |
181
|
|
|
|
|
|
|
... |
182
|
|
|
|
|
|
|
} |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
Each route subroutine receives C<$self> and all named placeholders. |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
route '/:id/:page' => sub { |
187
|
|
|
|
|
|
|
my ( $self, $id, $page ) = @_; |
188
|
|
|
|
|
|
|
}; |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
Here, C<$self> is the app object and it can be used the same way as in a full |
191
|
|
|
|
|
|
|
L<Kelp> route. For the feeling of magic and eeriness, C<Kelp::Lite> aliases |
192
|
|
|
|
|
|
|
C<app> to C<$self>, so the former can be used as a full substitute to the |
193
|
|
|
|
|
|
|
latter. See the exported keywords section for more information. |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
After you have added all of your routes, it is time to run the app. This is done |
196
|
|
|
|
|
|
|
via a single command: |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
run; |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
It returns PSGI ready subroutine, so you can immediately deploy your new app via |
201
|
|
|
|
|
|
|
Plack: |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
> plackup myapp.psgi |
204
|
|
|
|
|
|
|
HTTP::Server::PSGI: Accepting connections at http://0:5000/ |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
=head1 KEYWORDS |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
The following list of keywords are exported to allow for less typing in |
209
|
|
|
|
|
|
|
C<Kelp::Less>: |
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
=head2 app |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
This a full alias for C<$self>. It is the application object, and an |
214
|
|
|
|
|
|
|
instance of the C<Kelp> class. You can use it for anything you would use |
215
|
|
|
|
|
|
|
C<$self> inside a route. |
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
route '/die' => sub { |
218
|
|
|
|
|
|
|
app->res->code(500); |
219
|
|
|
|
|
|
|
}; |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
=head2 attr |
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
Assigns lazy or active attributes (using L<Kelp::Base>) to C<app>. Use it to |
224
|
|
|
|
|
|
|
initialize your application. |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
attr mongo => MongoDB::MongoClient->new( ... ); |
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
=head2 route |
229
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
Adds a route to C<app>. It is an alias to C<$self-E<gt>routes-E<gt>add>, and requires |
231
|
|
|
|
|
|
|
the exact same parameters. See L<Kelp::Routes> for reference. |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
route '/get-it' => sub { "got it" }; |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
=head2 get, post, put, del |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
These are shortcuts to C<route> restricted to the corresponding HTTP method. |
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
get '/data' => sub { "Only works with GET" }; |
240
|
|
|
|
|
|
|
post '/data' => sub { "Only works with POST" }; |
241
|
|
|
|
|
|
|
put '/data' => sub { "Only works with PUT" }; |
242
|
|
|
|
|
|
|
del '/data' => sub { "Only works with DELETE" }; |
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
=head2 param |
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
An alias for C<$self-E<gt>param> that gets the GET or POST parameters. |
247
|
|
|
|
|
|
|
When used with no arguments, it will return an array with the names of all http |
248
|
|
|
|
|
|
|
parameters. Otherwise, it will return the value of the requested http parameter. |
249
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
get '/names' => sub { |
251
|
|
|
|
|
|
|
my @names = param; |
252
|
|
|
|
|
|
|
# Now @names contains the names of the params |
253
|
|
|
|
|
|
|
}; |
254
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
get '/value' => sub { |
256
|
|
|
|
|
|
|
my $id = param 'id'; |
257
|
|
|
|
|
|
|
# Now $is contains the value of 'id' |
258
|
|
|
|
|
|
|
}; |
259
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
=head2 stash |
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
An alias for C<$self-E<gt>stash>. The stash is a concept originally conceived by the |
263
|
|
|
|
|
|
|
developers of L<Catalyst>. It's a hash that you can use to pass data from one |
264
|
|
|
|
|
|
|
route to another. |
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
# Create a bridge route that checks if the user is authenticated, and saves |
267
|
|
|
|
|
|
|
# the username in the stash. |
268
|
|
|
|
|
|
|
get '/user' => { bridge => 1, to => sub { |
269
|
|
|
|
|
|
|
return stash->{username} = app->authenticate(); |
270
|
|
|
|
|
|
|
}}; |
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
# This route is run after the above bridge, so we know that we have an |
273
|
|
|
|
|
|
|
# authenticated user and their username in the stash. |
274
|
|
|
|
|
|
|
get '/user/welcome' => sub { |
275
|
|
|
|
|
|
|
return "Hello " . stash 'username'; |
276
|
|
|
|
|
|
|
}; |
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
With no arguments C<stash> returns the entire stash hash. A single argument is |
279
|
|
|
|
|
|
|
interpreted as the key to the stash hash and its value is returned accordingly. |
280
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
=head2 named |
282
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
An alias for C<$self-E<gt>named>. The C<named> hash contains the names and values of |
284
|
|
|
|
|
|
|
the named placeholders from the current route's path. Much like the C<stash>, |
285
|
|
|
|
|
|
|
with no arguments it returns the entire C<named> hash, and with a single |
286
|
|
|
|
|
|
|
argument it returns the value for the corresponding key in the hash. |
287
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
get '/:name/:id' => sub { |
289
|
|
|
|
|
|
|
my $name = named 'name'; |
290
|
|
|
|
|
|
|
my $id = name 'id'; |
291
|
|
|
|
|
|
|
}; |
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
In the above example a GET request to C</james/1000> will initialize C<$name> |
294
|
|
|
|
|
|
|
with C<"james"> and C<$id> with C<1000>. |
295
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
=head2 req |
297
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
An alias for C<$self-E<gt>req>, this provides quick access to the |
299
|
|
|
|
|
|
|
L<Kelp::Request> object for the current route. |
300
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
# Inside a route |
302
|
|
|
|
|
|
|
if ( req->is_ajax ) { |
303
|
|
|
|
|
|
|
... |
304
|
|
|
|
|
|
|
} |
305
|
|
|
|
|
|
|
|
306
|
|
|
|
|
|
|
=head2 res |
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
An alias for C<$self-E<gt>res>, this is a shortcut for the L<Kelp::Response> |
309
|
|
|
|
|
|
|
object for the current route. |
310
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
# Inside a route |
312
|
|
|
|
|
|
|
res->code(403); |
313
|
|
|
|
|
|
|
res->json->render({ message => "Forbidden" }); |
314
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
=head2 template |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
A shortcut to C<$self-E<gt>res-E<gt>template>. Renders a template using the |
318
|
|
|
|
|
|
|
currently loaded template module. Note that a Kelp::Less application does not |
319
|
|
|
|
|
|
|
by default load a template module, so you will have to load it yourself. |
320
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
use Kelp::Less; |
322
|
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
module 'Template', path => 'views'; |
324
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
get '/hello/:name' => sub { |
326
|
|
|
|
|
|
|
template 'hello.tt', { name => named 'name' }; |
327
|
|
|
|
|
|
|
}; |
328
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
=head2 view |
330
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
A shortcut for L</template>. |
332
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
get '/hello/:name' => sub { |
334
|
|
|
|
|
|
|
view 'hello.tt', { name => named 'name' }; |
335
|
|
|
|
|
|
|
}; |
336
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
=head2 run |
338
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
Creates and returns a PSGI ready subroutine, and makes the app ready for C<Plack>. |
340
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
=head2 module |
342
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
Loads a Kelp module. The module options may be specified after the module name. |
344
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
module 'JSON::XS', pretty => 1; |
346
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
=head2 config |
348
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
Provides procedural interface to the configuration. |
350
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
get '/hello' => sub { |
352
|
|
|
|
|
|
|
my $baz = config('bar.foo.baz'); |
353
|
|
|
|
|
|
|
}; |
354
|
|
|
|
|
|
|
|
355
|
|
|
|
|
|
|
=head1 TESTING |
356
|
|
|
|
|
|
|
|
357
|
|
|
|
|
|
|
When writing a C<Kelp::Less> app, we don't have a separate class to initialize and |
358
|
|
|
|
|
|
|
feed into a L<Kelp::Test> object, because all of our code is contained in the |
359
|
|
|
|
|
|
|
C<app.psgi> file. In this case, the C<Kelp::Test> object can be initialized |
360
|
|
|
|
|
|
|
with the name of the C<PSGI> file in the C<psgi> argument. |
361
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
# t/main.t |
363
|
|
|
|
|
|
|
use Kelp::Test; |
364
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
my $t = Kelp::Test->new( psgi => 'app.psgi' ); |
366
|
|
|
|
|
|
|
# Do some tests ... |
367
|
|
|
|
|
|
|
|
368
|
|
|
|
|
|
|
Since you don't have control over the creation of the C<Kelp> object, if you |
369
|
|
|
|
|
|
|
need to specify a different mode for testing, you can use the C<PLACK_ENV> |
370
|
|
|
|
|
|
|
environmental variable: |
371
|
|
|
|
|
|
|
|
372
|
|
|
|
|
|
|
> PLACK_ENV=test prove -l |
373
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
This will enable the C<conf/test.pl> configuration, which you should |
375
|
|
|
|
|
|
|
tailor to your testing needs. |
376
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
=head1 ACKNOWLEDGEMENTS |
378
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
This module's interface was inspired by L<Dancer>, which in its turn was |
380
|
|
|
|
|
|
|
inspired by Sinatra, so Viva La Open Source! |
381
|
|
|
|
|
|
|
|
382
|
|
|
|
|
|
|
=cut |