arg0 tests
[catagits/Catalyst-Runtime.git] / t / arg_constraints.t
1 use warnings;
2 use strict;
3 use HTTP::Request::Common;
4
5 BEGIN {
6   use Test::More;
7   eval "use Types::Standard; 1;" || do {
8     plan skip_all => "Trouble loading Types::Standard => $@";
9   };
10
11   package MyApp::Types;
12   $INC{'MyApp/Types.pm'} = __FILE__;
13
14   use strict;
15   use warnings;
16  
17   use Type::Utils -all;
18   use Types::Standard -types;
19   use Type::Library
20    -base,
21    -declare => qw( UserId User ContextLike );
22
23   extends "Types::Standard"; 
24
25   class_type User, { class => "MyApp::Model::User::user" };
26   duck_type ContextLike, [qw/model/];
27
28   declare UserId,
29    as Int,
30    where { $_ < 5 };
31
32   # Tests using this are skipped pending deeper thought
33   coerce User,
34    from ContextLike,
35      via { $_->model('User')->find( $_->req->args->[0] ) };
36 }
37
38 {
39   package MyApp::Model::User;
40   $INC{'MyApp/Model/User.pm'} = __FILE__;
41
42   use base 'Catalyst::Model';
43
44   our %users = (
45     1 => { name => 'john', age => 46 },
46     2 => { name => 'mary', age => 36 },
47     3 => { name => 'ian', age => 25 },
48     4 => { name => 'visha', age => 18 },
49   );
50
51   sub find {
52     my ($self, $id) = @_;
53     my $user = $users{$id} || return;
54     return bless $user, "MyApp::Model::User::user";
55   }
56
57   package MyApp::Controller::Root;
58   $INC{'MyApp/Controller/Root.pm'} = __FILE__;
59
60   use Moose;
61   use MooseX::MethodAttributes;
62   use MyApp::Types qw/Tuple Int Str StrMatch ArrayRef UserId User/;
63
64   extends 'Catalyst::Controller';
65
66   sub user :Local Args(UserId) {
67     my ($self, $c, $int) = @_;
68     my $user = $c->model("User")->find($int);
69     $c->res->body("name: $user->{name}, age: $user->{age}");
70   }
71
72   # Tests using this are current skipped pending coercion rethink
73   sub user_object :Local Args(User) Coerce(1) {
74     my ($self, $c, $user) = @_;
75     $c->res->body("name: $user->{name}, age: $user->{age}");
76   }
77
78   sub an_int :Local Args(Int) {
79     my ($self, $c, $int) = @_;
80     $c->res->body('an_int');
81   }
82
83   sub two_ints :Local Args(Int,Int) {
84     my ($self, $c, $int) = @_;
85     $c->res->body('two_ints');
86   }
87
88   sub many_ints :Local Args(ArrayRef[Int]) {
89     my ($self, $c, $int) = @_;
90     $c->res->body('many_ints');
91   }
92
93   sub tuple :Local Args(Tuple[Str,Int]) {
94     my ($self, $c, $str, $int) = @_;
95     $c->res->body('tuple');
96   }
97
98   sub match :Local Args(StrMatch[qr{\d\d-\d\d-\d\d}]) {
99     my ($self, $c, $int) = @_;
100     $c->res->body('match');
101   }
102
103   sub any_priority :Path('priority_test') Args(1) { $_[1]->res->body('any_priority') }
104
105   sub int_priority :Path('priority_test') Args(Int) { $_[1]->res->body('int_priority') }
106
107   sub chain_base :Chained(/) CaptureArgs(1) { }
108
109     sub chained_zero_post :POST Chained(chain_base) PathPart('') Args(0) { $_[1]->res->body('chained_zero_post') }
110     sub chained_zero      :     Chained(chain_base) PathPart('') Args(0) { $_[1]->res->body('chained_zero') }
111
112     sub any_priority_chain :GET Chained(chain_base) PathPart('') Args(1) { $_[1]->res->body('any_priority_chain') }
113
114     sub int_priority_chain :Chained(chain_base) PathPart('') Args(Int) { $_[1]->res->body('int_priority_chain') }
115
116     sub link_any :Chained(chain_base) PathPart('') CaptureArgs(1) { }
117
118       sub any_priority_link_any :Chained(link_any) PathPart('') Args(1) { $_[1]->res->body('any_priority_link_any') }
119
120       sub int_priority_link_any :Chained(link_any) PathPart('') Args(Int) { $_[1]->res->body('int_priority_link_any') }
121     
122     sub link_int :Chained(chain_base) PathPart('') CaptureArgs(Int) { }
123
124       sub any_priority_link :Chained(link_int) PathPart('') Args(1) { $_[1]->res->body('any_priority_link') }
125
126       sub int_priority_link :Chained(link_int) PathPart('') Args(Int) { $_[1]->res->body('int_priority_link') }
127
128     sub link_int_int :Chained(chain_base) PathPart('') CaptureArgs(Int,Int) { }
129
130       sub any_priority_link2 :Chained(link_int_int) PathPart('') Args(1) { $_[1]->res->body('any_priority_link2') }
131
132       sub int_priority_link2 :Chained(link_int_int) PathPart('') Args(Int) { $_[1]->res->body('int_priority_link2') }
133
134     sub link_tuple :Chained(chain_base) PathPart('') CaptureArgs(Tuple[Int,Int,Int]) { }
135
136       sub any_priority_link3 :Chained(link_tuple) PathPart('') Args(1) { $_[1]->res->body('any_priority_link3') }
137
138       sub int_priority_link3 :Chained(link_tuple) PathPart('') Args(Int) { $_[1]->res->body('int_priority_link3') }
139
140       sub link2_int :Chained(link_tuple) PathPart('') CaptureArgs(UserId) { }
141
142         sub finally2 :GET Chained(link2_int) PathPart('') Args { $_[1]->res->body('finally2') }
143         sub finally :GET Chained(link2_int) PathPart('') Args(Int) { $_[1]->res->body('finally') }
144
145   sub default :Default {
146     my ($self, $c, $int) = @_;
147     $c->res->body('default');
148   }
149
150   MyApp::Controller::Root->config(namespace=>'');
151
152   package MyApp;
153   use Catalyst;
154
155   MyApp->setup;
156 }
157
158 use Catalyst::Test 'MyApp';
159
160 {
161   my $res = request '/an_int/1';
162   is $res->content, 'an_int';
163 }
164
165 {
166   my $res = request '/an_int/aa';
167   is $res->content, 'default';
168 }
169
170 {
171   my $res = request '/many_ints/1';
172   is $res->content, 'many_ints';
173 }
174
175 {
176   my $res = request '/many_ints/1/2';
177   is $res->content, 'many_ints';
178 }
179
180 {
181   my $res = request '/many_ints/1/2/3';
182   is $res->content, 'many_ints';
183 }
184
185 {
186   my $res = request '/priority_test/1';
187   is $res->content, 'int_priority';
188 }
189
190 {
191   my $res = request '/priority_test/a';
192   is $res->content, 'any_priority';
193 }
194
195 {
196   my $res = request '/match/11-22-33';
197   is $res->content, 'match';
198 }
199
200 {
201   my $res = request '/match/aaa';
202   is $res->content, 'default';
203 }
204
205 {
206   my $res = request '/user/2';
207   is $res->content, 'name: mary, age: 36';
208 }
209
210 {
211   my $res = request '/user/20';
212   is $res->content, 'default';
213 }
214
215
216 SKIP: {
217   skip "coercion support needs more thought", 1;
218   my $res = request '/user_object/20';
219   is $res->content, 'default';
220 }
221
222 SKIP: {
223   skip "coercion support needs more thought", 1;
224   my $res = request '/user_object/2';
225   is $res->content, 'name: mary, age: 36';
226 }
227
228 {
229   my $res = request '/chain_base/capture/arg';
230   is $res->content, 'any_priority_chain';
231 }
232
233 {
234   my $res = request '/chain_base/cap1/100/arg';
235   is $res->content, 'any_priority_link';
236 }
237
238 {
239   my $res = request '/chain_base/cap1/101/102';
240   is $res->content, 'int_priority_link';
241 }
242
243 {
244   my $res = request '/chain_base/capture/100';
245   is $res->content, 'int_priority_chain', 'got expected';
246 }
247
248 {
249   my $res = request '/chain_base/cap1/a/arg';
250   is $res->content, 'any_priority_link_any';
251 }
252
253 {
254   my $res = request '/chain_base/cap1/a/102';
255   is $res->content, 'int_priority_link_any';
256 }
257
258 {
259   my $res = request '/two_ints/1/2';
260   is $res->content, 'two_ints';
261 }
262
263 {
264   my $res = request '/two_ints/aa/111';
265   is $res->content, 'default';
266 }
267
268 {
269   my $res = request '/tuple/aaa/aaa';
270   is $res->content, 'default';
271 }
272
273 {
274   my $res = request '/tuple/aaa/111';
275   is $res->content, 'tuple';
276 }
277
278 {
279   my $res = request '/many_ints/1/2/a';
280   is $res->content, 'default';
281 }
282
283 {
284   my $res = request '/chain_base/100/100/100/100';
285   is $res->content, 'int_priority_link2';
286 }
287
288 {
289   my $res = request '/chain_base/100/ss/100/100';
290   is $res->content, 'default';
291 }
292
293 {
294   my $res = request '/chain_base/100/100/100/100/100';
295   is $res->content, 'int_priority_link3';
296 }
297
298 {
299   my $res = request '/chain_base/100/ss/100/100/100';
300   is $res->content, 'default';
301 }
302
303 {
304   my $res = request '/chain_base/1/2/3/3/3/6';
305   is $res->content, 'finally';
306 }
307
308 {
309   my $res = request '/chain_base/1/2/3/3/3/a';
310   is $res->content, 'finally2';
311 }
312
313 {
314   my $res = request '/chain_base/1/2/3/3/3/6/7/8/9';
315   is $res->content, 'finally2';
316 }
317
318 =over
319
320 | /chain_base/*                                               | /chain_base (1)                                             |
321 |                                                             | => /chained_zero (0)                                        |
322 | /chain_base/*                                               | /chain_base (1)                                             |
323 |                                                             | => POST /chained_zero_post (0)                              
324
325 =cut
326
327 {
328     my $res = request PUT '/chain_base/capture';
329     is $res->content, 'chained_zero';
330 }
331
332 {
333     my $res = request '/chain_base/capture';
334     is $res->content, 'chained_zero';
335 }
336
337 {
338     my $res = request POST '/chain_base/capture';
339     is $res->content, 'chained_zero_post';
340 }
341
342 =over
343
344 | /chain_base/*/*/*/*/*/*                 | /chain_base (1)
345 |                                         | -> /link_tuple (Tuple[Int,Int,Int])
346 |                                         | -> /link2_int (UserId)
347 |                                         | => GET /finally (Int)
348
349 =cut
350
351 {
352   # URI testing
353   my ($res, $c) = ctx_request '/';
354   ok my $url1 = $c->uri_for($c->controller('Root')->action_for('finally'), [1,2,3,4,5],6);
355   warn $url1;
356
357   ok my $url2 = $c->uri_for($c->controller('Root')->action_for('finally'), [1,2,3,4,5,6]);
358   warn $url2;
359 }
360
361 done_testing;