Commit | Line | Data |
d91504e3 |
1 | use warnings; |
2 | use strict; |
b4037086 |
3 | use HTTP::Request::Common; |
d2b583c3 |
4 | use utf8; |
842180f7 |
5 | |
6 | BEGIN { |
7 | use Test::More; |
8748abc5 |
8 | eval "use Type::Tiny 1.000005; 1" || do { |
ea3943b8 |
9 | plan skip_all => "Trouble loading Type::Tiny and friends => $@"; |
842180f7 |
10 | }; |
ea3943b8 |
11 | } |
6f0b85d2 |
12 | |
ea3943b8 |
13 | BEGIN { |
6f0b85d2 |
14 | package MyApp::Types; |
15 | $INC{'MyApp/Types.pm'} = __FILE__; |
16 | |
17 | use strict; |
18 | use warnings; |
19 | |
20 | use Type::Utils -all; |
21 | use Types::Standard -types; |
22 | use Type::Library |
23 | -base, |
d2b583c3 |
24 | -declare => qw( UserId Heart User ContextLike ); |
6f0b85d2 |
25 | |
26 | extends "Types::Standard"; |
27 | |
28 | class_type User, { class => "MyApp::Model::User::user" }; |
29 | duck_type ContextLike, [qw/model/]; |
30 | |
31 | declare UserId, |
32 | as Int, |
33 | where { $_ < 5 }; |
34 | |
d2b583c3 |
35 | declare Heart, |
36 | as Str, |
37 | where { $_ eq '♥' }; |
38 | |
a7ab9aa9 |
39 | # Tests using this are skipped pending deeper thought |
6f0b85d2 |
40 | coerce User, |
41 | from ContextLike, |
42 | via { $_->model('User')->find( $_->req->args->[0] ) }; |
842180f7 |
43 | } |
d91504e3 |
44 | |
45 | { |
6f0b85d2 |
46 | package MyApp::Model::User; |
47 | $INC{'MyApp/Model/User.pm'} = __FILE__; |
48 | |
49 | use base 'Catalyst::Model'; |
50 | |
51 | our %users = ( |
52 | 1 => { name => 'john', age => 46 }, |
53 | 2 => { name => 'mary', age => 36 }, |
54 | 3 => { name => 'ian', age => 25 }, |
55 | 4 => { name => 'visha', age => 18 }, |
56 | ); |
57 | |
58 | sub find { |
59 | my ($self, $id) = @_; |
60 | my $user = $users{$id} || return; |
61 | return bless $user, "MyApp::Model::User::user"; |
62 | } |
63 | |
d91504e3 |
64 | package MyApp::Controller::Root; |
65 | $INC{'MyApp/Controller/Root.pm'} = __FILE__; |
66 | |
67 | use Moose; |
68 | use MooseX::MethodAttributes; |
d9f0a350 |
69 | use Types::Standard qw/slurpy/; |
d2b583c3 |
70 | use MyApp::Types qw/Tuple Int Str StrMatch ArrayRef UserId User Heart/; |
d91504e3 |
71 | |
72 | extends 'Catalyst::Controller'; |
73 | |
6f0b85d2 |
74 | sub user :Local Args(UserId) { |
75 | my ($self, $c, $int) = @_; |
76 | my $user = $c->model("User")->find($int); |
77 | $c->res->body("name: $user->{name}, age: $user->{age}"); |
78 | } |
79 | |
a7ab9aa9 |
80 | # Tests using this are current skipped pending coercion rethink |
6f0b85d2 |
81 | sub user_object :Local Args(User) Coerce(1) { |
82 | my ($self, $c, $user) = @_; |
83 | $c->res->body("name: $user->{name}, age: $user->{age}"); |
84 | } |
85 | |
75ce30d0 |
86 | sub stringy_enum :Local Args('Int',Int) { |
87 | my ($self, $c) = @_; |
88 | $c->res->body('enum'); |
89 | } |
90 | |
6d62355b |
91 | sub an_int :Local Args(Int) { |
92 | my ($self, $c, $int) = @_; |
6d62355b |
93 | $c->res->body('an_int'); |
94 | } |
95 | |
bf4f1643 |
96 | sub two_ints :Local Args(Int,Int) { |
97 | my ($self, $c, $int) = @_; |
98 | $c->res->body('two_ints'); |
99 | } |
100 | |
4a0218ca |
101 | sub many_ints :Local Args(ArrayRef[Int]) { |
d9f0a350 |
102 | my ($self, $c, @ints) = @_; |
4a0218ca |
103 | $c->res->body('many_ints'); |
104 | } |
105 | |
842180f7 |
106 | sub tuple :Local Args(Tuple[Str,Int]) { |
6f0b85d2 |
107 | my ($self, $c, $str, $int) = @_; |
842180f7 |
108 | $c->res->body('tuple'); |
109 | } |
110 | |
d9f0a350 |
111 | sub slurpy_tuple :Local Args(Tuple[Str,Int, slurpy ArrayRef[Int]]) { |
112 | my ($self, $c, $str, $int) = @_; |
113 | $c->res->body('tuple'); |
114 | } |
115 | |
6f0b85d2 |
116 | sub match :Local Args(StrMatch[qr{\d\d-\d\d-\d\d}]) { |
117 | my ($self, $c, $int) = @_; |
118 | $c->res->body('match'); |
119 | } |
a82c96cf |
120 | |
e5604544 |
121 | sub any_priority :Path('priority_test') Args(1) { $_[1]->res->body('any_priority') } |
842180f7 |
122 | |
b7791bd7 |
123 | sub int_priority :Path('priority_test') Args(Int) { $_[1]->res->body('int_priority') } |
e5604544 |
124 | |
a82c96cf |
125 | sub chain_base :Chained(/) CaptureArgs(1) { } |
126 | |
90102012 |
127 | sub any_priority_chain :GET Chained(chain_base) PathPart('') Args(1) { $_[1]->res->body('any_priority_chain') } |
a82c96cf |
128 | |
129 | sub int_priority_chain :Chained(chain_base) PathPart('') Args(Int) { $_[1]->res->body('int_priority_chain') } |
130 | |
480d94b5 |
131 | sub link_any :Chained(chain_base) PathPart('') CaptureArgs(1) { } |
132 | |
133 | sub any_priority_link_any :Chained(link_any) PathPart('') Args(1) { $_[1]->res->body('any_priority_link_any') } |
134 | |
135 | sub int_priority_link_any :Chained(link_any) PathPart('') Args(Int) { $_[1]->res->body('int_priority_link_any') } |
136 | |
a82c96cf |
137 | sub link_int :Chained(chain_base) PathPart('') CaptureArgs(Int) { } |
138 | |
139 | sub any_priority_link :Chained(link_int) PathPart('') Args(1) { $_[1]->res->body('any_priority_link') } |
140 | |
141 | sub int_priority_link :Chained(link_int) PathPart('') Args(Int) { $_[1]->res->body('int_priority_link') } |
142 | |
677c155c |
143 | sub link_int_int :Chained(chain_base) PathPart('') CaptureArgs(Int,Int) { } |
bf4f1643 |
144 | |
145 | sub any_priority_link2 :Chained(link_int_int) PathPart('') Args(1) { $_[1]->res->body('any_priority_link2') } |
146 | |
147 | sub int_priority_link2 :Chained(link_int_int) PathPart('') Args(Int) { $_[1]->res->body('int_priority_link2') } |
148 | |
677c155c |
149 | sub link_tuple :Chained(chain_base) PathPart('') CaptureArgs(Tuple[Int,Int,Int]) { } |
150 | |
151 | sub any_priority_link3 :Chained(link_tuple) PathPart('') Args(1) { $_[1]->res->body('any_priority_link3') } |
152 | |
153 | sub int_priority_link3 :Chained(link_tuple) PathPart('') Args(Int) { $_[1]->res->body('int_priority_link3') } |
154 | |
b6847871 |
155 | sub link2_int :Chained(link_tuple) PathPart('') CaptureArgs(UserId) { } |
156 | |
79b7db20 |
157 | sub finally2 :GET Chained(link2_int) PathPart('') Args { $_[1]->res->body('finally2') } |
90102012 |
158 | sub finally :GET Chained(link2_int) PathPart('') Args(Int) { $_[1]->res->body('finally') } |
a82c96cf |
159 | |
aef0cb5d |
160 | sub chain_base2 :Chained(/) CaptureArgs(1) { } |
161 | |
70949f28 |
162 | sub chained_zero_again : Chained(chain_base2) PathPart('') Args(0) { $_[1]->res->body('chained_zero_again') } |
163 | sub chained_zero_post2 : Chained(chain_base2) PathPart('') Args(0) { $_[1]->res->body('chained_zero_post2') } |
aef0cb5d |
164 | sub chained_zero2 : Chained(chain_base2) PathPart('') Args(0) { $_[1]->res->body('chained_zero2') } |
165 | |
70949f28 |
166 | sub chained_zero_post3 : Chained(chain_base2) PathPart('') Args(1) { $_[1]->res->body('chained_zero_post3') } |
aef0cb5d |
167 | sub chained_zero3 : Chained(chain_base2) PathPart('') Args(1) { $_[1]->res->body('chained_zero3') } |
168 | |
169 | |
d2b583c3 |
170 | sub heart :Local Args(Heart) { } |
171 | |
172 | sub utf8_base :Chained(/) CaptureArgs(Heart) { } |
173 | sub utf8_end :Chained(utf8_base) PathPart('') Args(Heart) { } |
174 | |
6d62355b |
175 | sub default :Default { |
176 | my ($self, $c, $int) = @_; |
177 | $c->res->body('default'); |
d91504e3 |
178 | } |
179 | |
180 | MyApp::Controller::Root->config(namespace=>''); |
181 | |
182 | package MyApp; |
183 | use Catalyst; |
184 | |
185 | MyApp->setup; |
186 | } |
187 | |
188 | use Catalyst::Test 'MyApp'; |
189 | |
190 | { |
6d62355b |
191 | my $res = request '/an_int/1'; |
192 | is $res->content, 'an_int'; |
193 | } |
194 | |
195 | { |
337a627a |
196 | my $res = request '/an_int/aa'; |
197 | is $res->content, 'default'; |
198 | } |
199 | |
200 | { |
4a0218ca |
201 | my $res = request '/many_ints/1'; |
202 | is $res->content, 'many_ints'; |
203 | } |
204 | |
205 | { |
206 | my $res = request '/many_ints/1/2'; |
207 | is $res->content, 'many_ints'; |
208 | } |
209 | |
210 | { |
211 | my $res = request '/many_ints/1/2/3'; |
212 | is $res->content, 'many_ints'; |
213 | } |
214 | |
215 | { |
e5604544 |
216 | my $res = request '/priority_test/1'; |
217 | is $res->content, 'int_priority'; |
218 | } |
842180f7 |
219 | |
e5604544 |
220 | { |
221 | my $res = request '/priority_test/a'; |
222 | is $res->content, 'any_priority'; |
223 | } |
224 | |
842180f7 |
225 | { |
6f0b85d2 |
226 | my $res = request '/match/11-22-33'; |
227 | is $res->content, 'match'; |
228 | } |
81436df9 |
229 | |
6f0b85d2 |
230 | { |
231 | my $res = request '/match/aaa'; |
232 | is $res->content, 'default'; |
233 | } |
234 | |
235 | { |
236 | my $res = request '/user/2'; |
237 | is $res->content, 'name: mary, age: 36'; |
238 | } |
239 | |
240 | { |
241 | my $res = request '/user/20'; |
242 | is $res->content, 'default'; |
243 | } |
244 | |
a7ab9aa9 |
245 | |
246 | SKIP: { |
247 | skip "coercion support needs more thought", 1; |
6f0b85d2 |
248 | my $res = request '/user_object/20'; |
249 | is $res->content, 'default'; |
250 | } |
251 | |
a7ab9aa9 |
252 | SKIP: { |
253 | skip "coercion support needs more thought", 1; |
6f0b85d2 |
254 | my $res = request '/user_object/2'; |
255 | is $res->content, 'name: mary, age: 36'; |
256 | } |
257 | |
a82c96cf |
258 | { |
259 | my $res = request '/chain_base/capture/arg'; |
260 | is $res->content, 'any_priority_chain'; |
261 | } |
262 | |
263 | { |
264 | my $res = request '/chain_base/cap1/100/arg'; |
265 | is $res->content, 'any_priority_link'; |
266 | } |
267 | |
268 | { |
269 | my $res = request '/chain_base/cap1/101/102'; |
270 | is $res->content, 'int_priority_link'; |
271 | } |
272 | |
273 | { |
274 | my $res = request '/chain_base/capture/100'; |
275 | is $res->content, 'int_priority_chain', 'got expected'; |
276 | } |
277 | |
480d94b5 |
278 | { |
279 | my $res = request '/chain_base/cap1/a/arg'; |
280 | is $res->content, 'any_priority_link_any'; |
281 | } |
282 | |
283 | { |
284 | my $res = request '/chain_base/cap1/a/102'; |
285 | is $res->content, 'int_priority_link_any'; |
286 | } |
287 | |
bf4f1643 |
288 | { |
289 | my $res = request '/two_ints/1/2'; |
290 | is $res->content, 'two_ints'; |
291 | } |
292 | |
293 | { |
294 | my $res = request '/two_ints/aa/111'; |
295 | is $res->content, 'default'; |
296 | } |
297 | |
298 | { |
299 | my $res = request '/tuple/aaa/aaa'; |
300 | is $res->content, 'default'; |
301 | } |
302 | |
303 | { |
304 | my $res = request '/tuple/aaa/111'; |
305 | is $res->content, 'tuple'; |
306 | } |
307 | |
308 | { |
d9f0a350 |
309 | my $res = request '/tuple/aaa/111/111/111'; |
310 | is $res->content, 'default'; |
311 | } |
312 | |
313 | { |
314 | my $res = request '/slurpy_tuple/aaa/111/111/111'; |
315 | is $res->content, 'tuple'; |
316 | } |
317 | |
318 | |
319 | { |
bf4f1643 |
320 | my $res = request '/many_ints/1/2/a'; |
321 | is $res->content, 'default'; |
322 | } |
323 | |
324 | { |
325 | my $res = request '/chain_base/100/100/100/100'; |
326 | is $res->content, 'int_priority_link2'; |
327 | } |
328 | |
329 | { |
330 | my $res = request '/chain_base/100/ss/100/100'; |
331 | is $res->content, 'default'; |
332 | } |
333 | |
677c155c |
334 | { |
335 | my $res = request '/chain_base/100/100/100/100/100'; |
336 | is $res->content, 'int_priority_link3'; |
337 | } |
338 | |
339 | { |
340 | my $res = request '/chain_base/100/ss/100/100/100'; |
341 | is $res->content, 'default'; |
342 | } |
343 | |
79b7db20 |
344 | { |
345 | my $res = request '/chain_base/1/2/3/3/3/6'; |
346 | is $res->content, 'finally'; |
347 | } |
348 | |
349 | { |
350 | my $res = request '/chain_base/1/2/3/3/3/a'; |
351 | is $res->content, 'finally2'; |
352 | } |
bf4f1643 |
353 | |
79b7db20 |
354 | { |
355 | my $res = request '/chain_base/1/2/3/3/3/6/7/8/9'; |
356 | is $res->content, 'finally2'; |
357 | } |
358 | |
b4037086 |
359 | |
360 | { |
aef0cb5d |
361 | my $res = request PUT '/chain_base2/capture/1'; |
70949f28 |
362 | is $res->content, 'chained_zero3', "request PUT '/chain_base2/capture/1'"; |
aef0cb5d |
363 | } |
364 | |
365 | { |
366 | my $res = request '/chain_base2/capture/1'; |
70949f28 |
367 | is $res->content, 'chained_zero3', "request '/chain_base2/capture/1'"; |
aef0cb5d |
368 | } |
369 | |
370 | { |
371 | my $res = request POST '/chain_base2/capture/1'; |
70949f28 |
372 | is $res->content, 'chained_zero3', "request POST '/chain_base2/capture/1'"; |
aef0cb5d |
373 | } |
374 | |
375 | { |
376 | my $res = request PUT '/chain_base2/capture'; |
70949f28 |
377 | is $res->content, 'chained_zero2', "request PUT '/chain_base2/capture'"; |
b4037086 |
378 | } |
379 | |
380 | { |
aef0cb5d |
381 | my $res = request '/chain_base2/capture'; |
70949f28 |
382 | is $res->content, 'chained_zero2', "request '/chain_base2/capture'"; |
b4037086 |
383 | } |
384 | |
385 | { |
aef0cb5d |
386 | my $res = request POST '/chain_base2/capture'; |
70949f28 |
387 | is $res->content, 'chained_zero2', "request POST '/chain_base2/capture'"; |
b4037086 |
388 | } |
389 | |
75ce30d0 |
390 | { |
391 | my $res = request '/stringy_enum/1/2'; |
392 | is $res->content, 'enum', "request '/stringy_enum/a'"; |
393 | } |
394 | |
395 | { |
396 | my $res = request '/stringy_enum/b/2'; |
397 | is $res->content, 'default', "request '/stringy_enum/a'"; |
398 | } |
399 | |
400 | { |
401 | my $res = request '/stringy_enum/1/a'; |
402 | is $res->content, 'default', "request '/stringy_enum/a'"; |
403 | } |
404 | |
b4037086 |
405 | =over |
406 | |
407 | | /chain_base/*/*/*/*/*/* | /chain_base (1) |
408 | | | -> /link_tuple (Tuple[Int,Int,Int]) |
409 | | | -> /link2_int (UserId) |
410 | | | => GET /finally (Int) |
411 | |
b6847871 |
412 | =cut |
413 | |
414 | { |
415 | # URI testing |
416 | my ($res, $c) = ctx_request '/'; |
b6847871 |
417 | |
86a399db |
418 | { |
419 | ok my $url = eval { $c->uri_for($c->controller('Root')->action_for('user'), 2) }; |
420 | is $url, 'http://localhost/user/2'; |
421 | } |
c1192f1e |
422 | |
86a399db |
423 | { |
424 | ok my $url = eval { $c->uri_for($c->controller('Root')->action_for('user'), [2]) }; |
425 | is $url, 'http://localhost/user/2'; |
426 | } |
c1192f1e |
427 | |
86a399db |
428 | { |
429 | ok my $url = ! eval { $c->uri_for($c->controller('Root')->action_for('user'), [20]) }; |
430 | } |
431 | |
432 | { |
433 | ok my $url = eval { $c->uri_for($c->controller('Root')->action_for('finally'), [1,2,3,4,4],6) }; |
434 | is $url, 'http://localhost/chain_base/1/2/3/4/4/6'; |
435 | } |
436 | |
437 | { |
438 | ok my $url = eval { $c->uri_for($c->controller('Root')->action_for('finally'), [1,2,3,4,4,6]) }; |
439 | is $url, 'http://localhost/chain_base/1/2/3/4/4/6'; |
440 | } |
441 | |
442 | { |
443 | ok my $url = ! eval { $c->uri_for($c->controller('Root')->action_for('finally'), [1,2,3,4,5,6]) }; |
444 | } |
445 | |
446 | { |
447 | ok my $url = eval { $c->uri_for($c->controller('Root')->action_for('finally'), ['a',2,3,4,4,6]) }; |
448 | is $url, 'http://localhost/chain_base/a/2/3/4/4/6'; |
449 | } |
450 | |
451 | { |
452 | ok my $url = ! eval { $c->uri_for($c->controller('Root')->action_for('finally'), ['a','1',3,4,4,'a']) }; |
453 | } |
454 | |
455 | { |
456 | ok my $url = ! eval { $c->uri_for($c->controller('Root')->action_for('finally'), ['a','a',3,4,4,'6']) }; |
457 | } |
c1192f1e |
458 | |
d2b583c3 |
459 | { |
460 | ok my $url = eval { $c->uri_for($c->controller('Root')->action_for('heart'), ['♥']) }; |
461 | is $url, 'http://localhost/heart/%E2%99%A5'; |
462 | } |
cbe13760 |
463 | |
d2b583c3 |
464 | { |
465 | ok my $url = ! eval { $c->uri_for($c->controller('Root')->action_for('heart'), ['1']) }; |
466 | } |
86a399db |
467 | |
d2b583c3 |
468 | { |
469 | ok my $url = eval { $c->uri_for($c->controller('Root')->action_for('utf8_end'), ['♥','♥']) }; |
470 | is $url, 'http://localhost/utf8_base/%E2%99%A5/%E2%99%A5'; |
471 | } |
cbe13760 |
472 | |
d2b583c3 |
473 | { |
474 | ok my $url = ! eval { $c->uri_for($c->controller('Root')->action_for('utf8_end'), ['2','1']) }; |
475 | } |
cbe13760 |
476 | |
d2b583c3 |
477 | } |
86a399db |
478 | |
d2b583c3 |
479 | done_testing; |