Fix typo in Catalyst::Engine confess()
[catagits/Catalyst-Runtime.git] / t / aggregate / live_component_controller_action_chained.t
CommitLineData
141459fa 1#!perl
2
3use strict;
4use warnings;
5
6use FindBin;
42da66a9 7use lib "$FindBin::Bin/../lib";
141459fa 8
9our $iters;
10
6b25e555 11BEGIN { $iters = $ENV{CAT_BENCH_ITERS} || 1; }
141459fa 12
36c67dc1 13use Test::More;
d527814d 14use URI;
15use URI::QueryParam;
141459fa 16use Catalyst::Test 'TestApp';
17
18if ( $ENV{CAT_BENCHMARK} ) {
19 require Benchmark;
20 Benchmark::timethis( $iters, \&run_tests );
21}
22else {
23 for ( 1 .. $iters ) {
8a6a6581 24 run_tests($_);
141459fa 25 }
26}
922c58d6 27
141459fa 28sub run_tests {
8a6a6581 29 my ($run_number) = @_;
d416846e 30
31 #
32 # This is a simple test where the parent and child actions are
33 # within the same controller.
34 #
141459fa 35 {
36 my @expected = qw[
5882c86e 37 TestApp::Controller::Action::Chained->begin
38 TestApp::Controller::Action::Chained->foo
39 TestApp::Controller::Action::Chained->endpoint
40 TestApp::Controller::Action::Chained->end
141459fa 41 ];
922c58d6 42
141459fa 43 my $expected = join( ", ", @expected );
922c58d6 44
5882c86e 45 ok( my $response = request('http://localhost/chained/foo/1/end/2'), 'chained + local endpoint' );
141459fa 46 is( $response->header('X-Catalyst-Executed'),
47 $expected, 'Executed actions' );
48 is( $response->content, '1; 2', 'Content OK' );
49 }
d416846e 50
51 #
52 # This makes sure the above isn't found if the argument for the
53 # end action isn't supplied.
54 #
55 {
56 my $expected = undef;
57
5882c86e 58 ok( my $response = request('http://localhost/chained/foo/1/end'),
59 'chained + local endpoint; missing last argument' );
d416846e 60 is( $response->header('X-Catalyst-Executed'),
61 $expected, 'Executed actions' );
10ae2631 62 is( $response->code, 500, 'Status OK' );
d416846e 63 }
64
65 #
66 # Tests the case when the child action is placed in a subcontroller.
67 #
141459fa 68 {
69 my @expected = qw[
5882c86e 70 TestApp::Controller::Action::Chained->begin
71 TestApp::Controller::Action::Chained->foo
72 TestApp::Controller::Action::Chained::Foo->spoon
73 TestApp::Controller::Action::Chained->end
141459fa 74 ];
922c58d6 75
141459fa 76 my $expected = join( ", ", @expected );
922c58d6 77
5882c86e 78 ok( my $response = request('http://localhost/chained/foo/1/spoon'), 'chained + subcontroller endpoint' );
141459fa 79 is( $response->header('X-Catalyst-Executed'),
80 $expected, 'Executed actions' );
81 is( $response->content, '1; ', 'Content OK' );
82 }
d416846e 83
84 #
5882c86e 85 # Tests if the relative specification (e.g.: Chained('bar') ) works
d416846e 86 # as expected.
87 #
141459fa 88 {
89 my @expected = qw[
5882c86e 90 TestApp::Controller::Action::Chained->begin
91 TestApp::Controller::Action::Chained->bar
92 TestApp::Controller::Action::Chained->finale
93 TestApp::Controller::Action::Chained->end
141459fa 94 ];
922c58d6 95
141459fa 96 my $expected = join( ", ", @expected );
922c58d6 97
5882c86e 98 ok( my $response = request('http://localhost/chained/bar/1/spoon'), 'chained + relative endpoint' );
141459fa 99 is( $response->header('X-Catalyst-Executed'),
100 $expected, 'Executed actions' );
101 is( $response->content, '; 1, spoon', 'Content OK' );
102 }
d416846e 103
104 #
105 # Just a test for multiple arguments.
106 #
922c58d6 107 {
108 my @expected = qw[
5882c86e 109 TestApp::Controller::Action::Chained->begin
110 TestApp::Controller::Action::Chained->foo2
111 TestApp::Controller::Action::Chained->endpoint2
112 TestApp::Controller::Action::Chained->end
922c58d6 113 ];
114
115 my $expected = join( ", ", @expected );
116
5882c86e 117 ok( my $response = request('http://localhost/chained/foo2/10/20/end2/15/25'),
118 'chained + local (2 args each)' );
922c58d6 119 is( $response->header('X-Catalyst-Executed'),
120 $expected, 'Executed actions' );
121 is( $response->content, '10, 20; 15, 25', 'Content OK' );
122 }
d416846e 123
124 #
125 # The first three-chain test tries to call the action with :Args(1)
1c34f703 126 # specification. There's also a one action with a :CaptureArgs(1)
d416846e 127 # attribute, that should not be dispatched to.
128 #
922c58d6 129 {
130 my @expected = qw[
5882c86e 131 TestApp::Controller::Action::Chained->begin
132 TestApp::Controller::Action::Chained->one_end
133 TestApp::Controller::Action::Chained->end
922c58d6 134 ];
135
136 my $expected = join( ", ", @expected );
137
5882c86e 138 ok( my $response = request('http://localhost/chained/one/23'),
922c58d6 139 'three-chain (only first)' );
140 is( $response->header('X-Catalyst-Executed'),
141 $expected, 'Executed actions' );
142 is( $response->content, '; 23', 'Content OK' );
143 }
d416846e 144
145 #
146 # This is the second three-chain test, it goes for the action that
147 # handles "/one/$cap/two/$arg1/$arg2" paths. Should be the two action
1c34f703 148 # having :Args(2), not the one having :CaptureArgs(2).
d416846e 149 #
922c58d6 150 {
151 my @expected = qw[
5882c86e 152 TestApp::Controller::Action::Chained->begin
153 TestApp::Controller::Action::Chained->one
154 TestApp::Controller::Action::Chained->two_end
155 TestApp::Controller::Action::Chained->end
922c58d6 156 ];
157
158 my $expected = join( ", ", @expected );
159
5882c86e 160 ok( my $response = request('http://localhost/chained/one/23/two/23/46'),
922c58d6 161 'three-chain (up to second)' );
162 is( $response->header('X-Catalyst-Executed'),
163 $expected, 'Executed actions' );
164 is( $response->content, '23; 23, 46', 'Content OK' );
165 }
d416846e 166
167 #
1c34f703 168 # Last of the three-chain tests. Has no concurrent action with :CaptureArgs
d416846e 169 # and is more thought to simply test the chain as a whole and the 'two'
1c34f703 170 # action specifying :CaptureArgs.
d416846e 171 #
922c58d6 172 {
173 my @expected = qw[
5882c86e 174 TestApp::Controller::Action::Chained->begin
175 TestApp::Controller::Action::Chained->one
176 TestApp::Controller::Action::Chained->two
177 TestApp::Controller::Action::Chained->three_end
178 TestApp::Controller::Action::Chained->end
922c58d6 179 ];
180
181 my $expected = join( ", ", @expected );
182
5882c86e 183 ok( my $response = request('http://localhost/chained/one/23/two/23/46/three/1/2/3'),
922c58d6 184 'three-chain (all three)' );
185 is( $response->header('X-Catalyst-Executed'),
186 $expected, 'Executed actions' );
187 is( $response->content, '23, 23, 46; 1, 2, 3', 'Content OK' );
188 }
d416846e 189
190 #
191 # Tests dispatching on number of arguments for :Args. This should be
192 # dispatched to the action expecting one argument.
193 #
922c58d6 194 {
195 my @expected = qw[
5882c86e 196 TestApp::Controller::Action::Chained->begin
197 TestApp::Controller::Action::Chained->multi1
198 TestApp::Controller::Action::Chained->end
922c58d6 199 ];
200
201 my $expected = join( ", ", @expected );
202
5882c86e 203 ok( my $response = request('http://localhost/chained/multi/23'),
922c58d6 204 'multi-action (one arg)' );
205 is( $response->header('X-Catalyst-Executed'),
206 $expected, 'Executed actions' );
207 is( $response->content, '; 23', 'Content OK' );
208 }
d416846e 209
210 #
211 # Belongs to the former test and goes for the action expecting two arguments.
212 #
922c58d6 213 {
214 my @expected = qw[
5882c86e 215 TestApp::Controller::Action::Chained->begin
216 TestApp::Controller::Action::Chained->multi2
217 TestApp::Controller::Action::Chained->end
922c58d6 218 ];
219
220 my $expected = join( ", ", @expected );
221
5882c86e 222 ok( my $response = request('http://localhost/chained/multi/23/46'),
922c58d6 223 'multi-action (two args)' );
224 is( $response->header('X-Catalyst-Executed'),
225 $expected, 'Executed actions' );
226 is( $response->content, '; 23, 46', 'Content OK' );
227 }
d416846e 228
229 #
230 # Dispatching on argument count again, this time we provide too many
231 # arguments, so dispatching should fail.
232 #
233 {
234 my $expected = undef;
235
5882c86e 236 ok( my $response = request('http://localhost/chained/multi/23/46/67'),
d416846e 237 'multi-action (three args, should lead to error)' );
238 is( $response->header('X-Catalyst-Executed'),
239 $expected, 'Executed actions' );
10ae2631 240 is( $response->code, 500, 'Status OK' );
d416846e 241 }
242
243 #
244 # This tests the case when an action says it's the child of an action in
245 # a subcontroller.
246 #
247 {
248 my @expected = qw[
5882c86e 249 TestApp::Controller::Action::Chained->begin
250 TestApp::Controller::Action::Chained::Foo->higher_root
251 TestApp::Controller::Action::Chained->higher_root
252 TestApp::Controller::Action::Chained->end
d416846e 253 ];
254
255 my $expected = join( ", ", @expected );
256
5882c86e 257 ok( my $response = request('http://localhost/chained/higher_root/23/bar/11'),
d416846e 258 'root higher than child' );
259 is( $response->header('X-Catalyst-Executed'),
260 $expected, 'Executed actions' );
261 is( $response->content, '23; 11', 'Content OK' );
262 }
263
264 #
265 # Just a more complex version of the former test. It tests if a controller ->
266 # subcontroller -> controller dispatch works.
267 #
268 {
269 my @expected = qw[
5882c86e 270 TestApp::Controller::Action::Chained->begin
271 TestApp::Controller::Action::Chained->pcp1
272 TestApp::Controller::Action::Chained::Foo->pcp2
273 TestApp::Controller::Action::Chained->pcp3
274 TestApp::Controller::Action::Chained->end
d416846e 275 ];
276
277 my $expected = join( ", ", @expected );
278
5882c86e 279 ok( my $response = request('http://localhost/chained/pcp1/1/pcp2/2/pcp3/3'),
d416846e 280 'parent -> child -> parent' );
281 is( $response->header('X-Catalyst-Executed'),
282 $expected, 'Executed actions' );
283 is( $response->content, '1, 2; 3', 'Content OK' );
284 }
285
286 #
287 # Tests dispatch on capture number. This test is for a one capture action.
288 #
289 {
290 my @expected = qw[
5882c86e 291 TestApp::Controller::Action::Chained->begin
292 TestApp::Controller::Action::Chained->multi_cap1
293 TestApp::Controller::Action::Chained->multi_cap_end1
294 TestApp::Controller::Action::Chained->end
d416846e 295 ];
296
297 my $expected = join( ", ", @expected );
298
5882c86e 299 ok( my $response = request('http://localhost/chained/multi_cap/1/baz'),
d416846e 300 'dispatch on capture num 1' );
301 is( $response->header('X-Catalyst-Executed'),
302 $expected, 'Executed actions' );
303 is( $response->content, '1; ', 'Content OK' );
304 }
305
306 #
307 # Belongs to the former test. This one goes for the action expecting two
308 # captures.
309 #
310 {
311 my @expected = qw[
5882c86e 312 TestApp::Controller::Action::Chained->begin
313 TestApp::Controller::Action::Chained->multi_cap2
314 TestApp::Controller::Action::Chained->multi_cap_end2
315 TestApp::Controller::Action::Chained->end
d416846e 316 ];
317
318 my $expected = join( ", ", @expected );
319
5882c86e 320 ok( my $response = request('http://localhost/chained/multi_cap/1/2/baz'),
d416846e 321 'dispatch on capture num 2' );
322 is( $response->header('X-Catalyst-Executed'),
323 $expected, 'Executed actions' );
324 is( $response->content, '1, 2; ', 'Content OK' );
325 }
326
327 #
328 # Tests the priority of a slurpy arguments action (with :Args) against
329 # two actions chained together. The two actions should win.
330 #
331 {
332 my @expected = qw[
5882c86e 333 TestApp::Controller::Action::Chained->begin
334 TestApp::Controller::Action::Chained->priority_a2
335 TestApp::Controller::Action::Chained->priority_a2_end
336 TestApp::Controller::Action::Chained->end
d416846e 337 ];
338
339 my $expected = join( ", ", @expected );
340
5882c86e 341 ok( my $response = request('http://localhost/chained/priority_a/1/end/2'),
d416846e 342 'priority - slurpy args vs. parent/child' );
343 is( $response->header('X-Catalyst-Executed'),
344 $expected, 'Executed actions' );
345 is( $response->content, '1; 2', 'Content OK' );
346 }
347
348 #
349 # This belongs to the former test but tests if two chained actions have
350 # priority over an action with the exact arguments.
351 #
352 {
353 my @expected = qw[
5882c86e 354 TestApp::Controller::Action::Chained->begin
355 TestApp::Controller::Action::Chained->priority_b2
356 TestApp::Controller::Action::Chained->priority_b2_end
357 TestApp::Controller::Action::Chained->end
d416846e 358 ];
359
360 my $expected = join( ", ", @expected );
361
5882c86e 362 ok( my $response = request('http://localhost/chained/priority_b/1/end/2'),
d416846e 363 'priority - fixed args vs. parent/child' );
364 is( $response->header('X-Catalyst-Executed'),
365 $expected, 'Executed actions' );
366 is( $response->content, '1; 2', 'Content OK' );
367 }
368
369 #
b7ce908f 370 # This belongs to the former test but tests if two chained actions have
371 # priority over an action with one child action not having the Args() attr set.
372 #
373 {
374 my @expected = qw[
375 TestApp::Controller::Action::Chained->begin
376 TestApp::Controller::Action::Chained->priority_c1
377 TestApp::Controller::Action::Chained->priority_c2_xyz
378 TestApp::Controller::Action::Chained->end
379 ];
380
381 my $expected = join( ", ", @expected );
382
383 ok( my $response = request('http://localhost/chained/priority_c/1/xyz/'),
384 'priority - no Args() order mismatch' );
385 is( $response->header('X-Catalyst-Executed'),
386 $expected, 'Executed actions' );
387 is( $response->content, '1; ', 'Content OK' );
388 }
389
390 #
d416846e 391 # Test dispatching between two controllers that are on the same level and
392 # therefor have no parent/child relationship.
393 #
394 {
395 my @expected = qw[
5882c86e 396 TestApp::Controller::Action::Chained->begin
397 TestApp::Controller::Action::Chained::Bar->cross1
398 TestApp::Controller::Action::Chained::Foo->cross2
399 TestApp::Controller::Action::Chained->end
d416846e 400 ];
401
402 my $expected = join( ", ", @expected );
403
5882c86e 404 ok( my $response = request('http://localhost/chained/cross/1/end/2'),
d416846e 405 'cross controller w/o par/child relation' );
406 is( $response->header('X-Catalyst-Executed'),
407 $expected, 'Executed actions' );
408 is( $response->content, '1; 2', 'Content OK' );
409 }
b25353e5 410
411 #
412 # This is for testing if the arguments got passed to the actions
413 # correctly.
414 #
415 {
416 my @expected = qw[
5882c86e 417 TestApp::Controller::Action::Chained->begin
418 TestApp::Controller::Action::Chained::PassedArgs->first
419 TestApp::Controller::Action::Chained::PassedArgs->second
420 TestApp::Controller::Action::Chained::PassedArgs->third
421 TestApp::Controller::Action::Chained::PassedArgs->end
b25353e5 422 ];
423
424 my $expected = join( ", ", @expected );
425
5882c86e 426 ok( my $response = request('http://localhost/chained/passedargs/a/1/b/2/c/3'),
b25353e5 427 'Correct arguments passed to actions' );
428 is( $response->header('X-Catalyst-Executed'),
429 $expected, 'Executed actions' );
430 is( $response->content, '1; 2; 3', 'Content OK' );
431 }
47f9968d 432
433 #
434 # The :Args attribute is optional, we check the action not specifying
435 # it with these tests.
436 #
437 {
438 my @expected = qw[
5882c86e 439 TestApp::Controller::Action::Chained->begin
440 TestApp::Controller::Action::Chained->opt_args
441 TestApp::Controller::Action::Chained->end
47f9968d 442 ];
443
444 my $expected = join( ", ", @expected );
445
5882c86e 446 ok( my $response = request('http://localhost/chained/opt_args/1/2/3'),
47f9968d 447 'Optional :Args attribute working' );
448 is( $response->header('X-Catalyst-Executed'),
449 $expected, 'Executed actions' );
450 is( $response->content, '; 1, 2, 3', 'Content OK' );
451 }
9cc84996 452
453 #
454 # Tests for optional PathPart attribute.
455 #
456 {
457 my @expected = qw[
5882c86e 458 TestApp::Controller::Action::Chained->begin
459 TestApp::Controller::Action::Chained->opt_pp_start
460 TestApp::Controller::Action::Chained->opt_pathpart
461 TestApp::Controller::Action::Chained->end
9cc84996 462 ];
463
464 my $expected = join( ", ", @expected );
465
5882c86e 466 ok( my $response = request('http://localhost/chained/optpp/1/opt_pathpart/2'),
9cc84996 467 'Optional :PathName attribute working' );
468 is( $response->header('X-Catalyst-Executed'),
469 $expected, 'Executed actions' );
470 is( $response->content, '1; 2', 'Content OK' );
471 }
472
473 #
474 # Tests for optional PathPart *and* Args attributes.
475 #
476 {
477 my @expected = qw[
5882c86e 478 TestApp::Controller::Action::Chained->begin
479 TestApp::Controller::Action::Chained->opt_all_start
480 TestApp::Controller::Action::Chained->oa
481 TestApp::Controller::Action::Chained->end
9cc84996 482 ];
483
484 my $expected = join( ", ", @expected );
485
5882c86e 486 ok( my $response = request('http://localhost/chained/optall/1/oa/2/3'),
9cc84996 487 'Optional :PathName *and* :Args attributes working' );
488 is( $response->header('X-Catalyst-Executed'),
489 $expected, 'Executed actions' );
490 is( $response->content, '1; 2, 3', 'Content OK' );
491 }
0e853a7f 492
493 #
494 # Test if :Chained is the same as :Chained('/')
495 #
496 {
497 my @expected = qw[
498 TestApp::Controller::Action::Chained->begin
499 TestApp::Controller::Action::Chained->rootdef
500 TestApp::Controller::Action::Chained->end
501 ];
502
503 my $expected = join( ", ", @expected );
504
505 ok( my $response = request('http://localhost/chained/rootdef/23'),
506 ":Chained is the same as :Chained('/')" );
507 is( $response->header('X-Catalyst-Executed'),
508 $expected, 'Executed actions' );
509 is( $response->content, '; 23', 'Content OK' );
510 }
511
512 #
f88e7f69 513 # Test if :Chained('.') is working
0e853a7f 514 #
515 {
516 my @expected = qw[
517 TestApp::Controller::Action::Chained->begin
518 TestApp::Controller::Action::Chained->parentchain
519 TestApp::Controller::Action::Chained::ParentChain->child
520 TestApp::Controller::Action::Chained->end
521 ];
522
523 my $expected = join( ", ", @expected );
524
525 ok( my $response = request('http://localhost/chained/parentchain/1/child/2'),
526 ":Chained('.') chains to parent controller action" );
527 is( $response->header('X-Catalyst-Executed'),
528 $expected, 'Executed actions' );
529 is( $response->content, '1; 2', 'Content OK' );
530 }
2349aeea 531
532 #
2f381252 533 # Test if :Chained('../act') is working
534 #
535 {
536 my @expected = qw[
537 TestApp::Controller::Action::Chained->begin
538 TestApp::Controller::Action::Chained->one
539 TestApp::Controller::Action::Chained::ParentChain->chained_rel
540 TestApp::Controller::Action::Chained->end
541 ];
542
543 my $expected = join( ", ", @expected );
544
545 ok( my $response = request('http://localhost/chained/one/1/chained_rel/3/2'),
546 ":Chained('../action') chains to correct action" );
547 is( $response->header('X-Catalyst-Executed'),
548 $expected, 'Executed actions' );
549 is( $response->content, '1; 3, 2', 'Content OK' );
550 }
551
552 #
553 # Test if ../ works to go up more than one level
554 #
555 {
556 my @expected = qw[
557 TestApp::Controller::Action::Chained->begin
558 TestApp::Controller::Action::Chained->one
559 TestApp::Controller::Action::Chained::ParentChain::Relative->chained_rel_two
560 TestApp::Controller::Action::Chained->end
561 ];
562
563 my $expected = join( ", ", @expected );
564
565 ok( my $response = request('http://localhost/chained/one/1/chained_rel_two/42/23'),
566 "../ works to go up more than one level" );
567 is( $response->header('X-Catalyst-Executed'),
568 $expected, 'Executed actions' );
569 is( $response->content, '1; 42, 23', 'Content OK' );
570 }
571
572 #
573 # Test if :ChainedParent is working
574 #
575 {
576 my @expected = qw[
577 TestApp::Controller::Action::Chained->begin
578 TestApp::Controller::Action::Chained->loose
579 TestApp::Controller::Action::Chained::ParentChain->loose
580 TestApp::Controller::Action::Chained->end
581 ];
582
583 my $expected = join( ", ", @expected );
584
585 ok( my $response = request('http://localhost/chained/loose/4/loose/a/b'),
586 ":Chained('../action') chains to correct action" );
587 is( $response->header('X-Catalyst-Executed'),
588 $expected, 'Executed actions' );
589 is( $response->content, '4; a, b', 'Content OK' );
590 }
591
592 #
593 # Test if :Chained('../name/act') is working
594 #
595 {
596 my @expected = qw[
597 TestApp::Controller::Action::Chained->begin
598 TestApp::Controller::Action::Chained::Bar->cross1
599 TestApp::Controller::Action::Chained::ParentChain->up_down
600 TestApp::Controller::Action::Chained->end
601 ];
602
603 my $expected = join( ", ", @expected );
604
605 ok( my $response = request('http://localhost/chained/cross/4/up_down/5'),
606 ":Chained('../action') chains to correct action" );
607 is( $response->header('X-Catalyst-Executed'),
608 $expected, 'Executed actions' );
609 is( $response->content, '4; 5', 'Content OK' );
610 }
611
612 #
2349aeea 613 # Test behaviour of auto actions returning '1' for the chain.
614 #
615 {
616 my @expected = qw[
617 TestApp::Controller::Action::Chained->begin
618 TestApp::Controller::Action::Chained::Auto->auto
619 TestApp::Controller::Action::Chained::Auto::Foo->auto
620 TestApp::Controller::Action::Chained::Auto->foo
621 TestApp::Controller::Action::Chained::Auto::Foo->fooend
622 TestApp::Controller::Action::Chained->end
623 ];
624
625 my $expected = join( ", ", @expected );
626
627 ok( my $response = request('http://localhost/chained/autochain1/1/fooend/2'),
628 "Behaviour when auto returns 1 correct" );
629 is( $response->header('X-Catalyst-Executed'),
630 $expected, 'Executed actions' );
631 is( $response->content, '1; 2', 'Content OK' );
632 }
633
634 #
635 # Test behaviour of auto actions returning '0' for the chain.
636 #
637 {
638 my @expected = qw[
639 TestApp::Controller::Action::Chained->begin
640 TestApp::Controller::Action::Chained::Auto->auto
641 TestApp::Controller::Action::Chained::Auto::Bar->auto
642 TestApp::Controller::Action::Chained->end
643 ];
644
645 my $expected = join( ", ", @expected );
646
647 ok( my $response = request('http://localhost/chained/autochain2/1/barend/2'),
648 "Behaviour when auto returns 0 correct" );
649 is( $response->header('X-Catalyst-Executed'),
650 $expected, 'Executed actions' );
651 is( $response->content, '1; 2', 'Content OK' );
652 }
653
654 #
655 # Test what auto actions are run when namespaces are changed
656 # horizontally.
657 #
658 {
659 my @expected = qw[
660 TestApp::Controller::Action::Chained->begin
661 TestApp::Controller::Action::Chained::Auto->auto
662 TestApp::Controller::Action::Chained::Auto::Foo->auto
663 TestApp::Controller::Action::Chained::Auto::Bar->crossloose
664 TestApp::Controller::Action::Chained::Auto::Foo->crossend
665 TestApp::Controller::Action::Chained->end
666 ];
667
668 my $expected = join( ", ", @expected );
669
670 ok( my $response = request('http://localhost/chained/auto_cross/1/crossend/2'),
671 "Correct auto actions are run on cross controller dispatch" );
672 is( $response->header('X-Catalyst-Executed'),
673 $expected, 'Executed actions' );
674 is( $response->content, '1; 2', 'Content OK' );
675 }
676
677 #
678 # Test forwarding from auto action in chain dispatch.
679 #
680 {
681 my @expected = qw[
682 TestApp::Controller::Action::Chained->begin
683 TestApp::Controller::Action::Chained::Auto->auto
684 TestApp::Controller::Action::Chained::Auto::Forward->auto
685 TestApp::Controller::Action::Chained::Auto->fw3
686 TestApp::Controller::Action::Chained::Auto->fw1
687 TestApp::Controller::Action::Chained::Auto::Forward->forwardend
688 TestApp::Controller::Action::Chained->end
689 ];
690
691 my $expected = join( ", ", @expected );
692
693 ok( my $response = request('http://localhost/chained/auto_forward/1/forwardend/2'),
694 "Forwarding out of auto in chain" );
695 is( $response->header('X-Catalyst-Executed'),
696 $expected, 'Executed actions' );
697 is( $response->content, '1; 2', 'Content OK' );
698 }
699
700 #
701 # Detaching out of the auto action of a chain.
702 #
703 {
704 my @expected = qw[
705 TestApp::Controller::Action::Chained->begin
706 TestApp::Controller::Action::Chained::Auto->auto
707 TestApp::Controller::Action::Chained::Auto::Detach->auto
708 TestApp::Controller::Action::Chained::Auto->fw3
709 TestApp::Controller::Action::Chained->end
710 ];
711
712 my $expected = join( ", ", @expected );
713
714 ok( my $response = request('http://localhost/chained/auto_detach/1/detachend/2'),
715 "Detaching out of auto in chain" );
716 is( $response->header('X-Catalyst-Executed'),
717 $expected, 'Executed actions' );
718 is( $response->content, '1; 2', 'Content OK' );
719 }
720
721 #
722 # Test forwarding from auto action in chain dispatch.
723 #
724 {
725 my $expected = undef;
726
727 ok( my $response = request('http://localhost/chained/loose/23'),
728 "Loose end is not callable" );
729 is( $response->header('X-Catalyst-Executed'),
730 $expected, 'Executed actions' );
10ae2631 731 is( $response->code, 500, 'Status OK' );
2349aeea 732 }
733
734 #
735 # Test forwarding out of a chain.
736 #
737 {
738 my @expected = qw[
739 TestApp::Controller::Action::Chained->begin
740 TestApp::Controller::Action::Chained->chain_fw_a
741 TestApp::Controller::Action::Chained->fw_dt_target
742 TestApp::Controller::Action::Chained->chain_fw_b
743 TestApp::Controller::Action::Chained->end
744 ];
745
746 my $expected = join( ", ", @expected );
747
748 ok( my $response = request('http://localhost/chained/chain_fw/1/end/2'),
749 "Forwarding out a chain" );
750 is( $response->header('X-Catalyst-Executed'),
751 $expected, 'Executed actions' );
752 is( $response->content, '1; 2', 'Content OK' );
753 }
754
755 #
756 # Test detaching out of a chain.
757 #
758 {
759 my @expected = qw[
760 TestApp::Controller::Action::Chained->begin
761 TestApp::Controller::Action::Chained->chain_dt_a
762 TestApp::Controller::Action::Chained->fw_dt_target
763 TestApp::Controller::Action::Chained->end
764 ];
765
766 my $expected = join( ", ", @expected );
767
768 ok( my $response = request('http://localhost/chained/chain_dt/1/end/2'),
769 "Forwarding out a chain" );
770 is( $response->header('X-Catalyst-Executed'),
771 $expected, 'Executed actions' );
772 is( $response->content, '1; 2', 'Content OK' );
773 }
8a6a6581 774
775 #
81e75875 776 # Tests that an uri_for to a chained root index action
777 # returns the right value.
778 #
779 {
780 ok( my $response = request(
781 'http://localhost/action/chained/to_root' ),
782 'uri_for with chained root action as arg' );
10ae2631 783 like( $response->content,
de19de2e 784 qr(URI:https?://[^/]+/),
81e75875 785 'Correct URI generated' );
786 }
787
788 #
8a6a6581 789 # Test interception of recursive chains. This test was added because at
790 # one point during the :Chained development, Catalyst used to hang on
791 # recursive chains.
792 #
793 {
794 eval { require 'TestAppChainedRecursive.pm' };
05a90578 795 if ($run_number == 1) {
796 ok( ! $@, "Interception of recursive chains" );
797 }
798 else { pass( "Interception of recursive chains already tested" ) }
8a6a6581 799 }
800
801 #
802 # Test failure of absolute path part arguments.
803 #
804 {
805 eval { require 'TestAppChainedAbsolutePathPart.pm' };
806 if ($run_number == 1) {
807 like( $@, qr(foo/foo),
808 "Usage of absolute path part argument emits error" );
809 }
810 else { pass( "Error on absolute path part arguments already tested" ) }
811 }
f505df49 812
813 #
caaf37ad 814 # Test chained actions in the root controller
815 #
816 {
817 my @expected = qw[
caaf37ad 818 TestApp::Controller::Action::Chained::Root->rootsub
819 TestApp::Controller::Action::Chained::Root->endpointsub
a0a66cb8 820 TestApp::Controller::Root->end
caaf37ad 821 ];
822
823 my $expected = join( ", ", @expected );
824
825 ok( my $response = request('http://localhost/rootsub/1/endpointsub/2'), 'chained in root namespace' );
826 is( $response->header('X-Catalyst-Executed'),
827 $expected, 'Executed actions' );
f720422c 828 is( $response->content, '', 'Content OK' );
caaf37ad 829 }
830
831 #
f505df49 832 # Complex path with multiple empty pathparts
833 #
834 {
835 my @expected = qw[
836 TestApp::Controller::Action::Chained->begin
837 TestApp::Controller::Action::Chained->mult_nopp_base
838 TestApp::Controller::Action::Chained->mult_nopp_all
839 TestApp::Controller::Action::Chained->end
840 ];
841
842 my $expected = join( ", ", @expected );
843
844 ok( my $response = request('http://localhost/chained/mult_nopp'),
845 "Complex path with multiple empty pathparts" );
846 is( $response->header('X-Catalyst-Executed'),
847 $expected, 'Executed actions' );
848 is( $response->content, '; ', 'Content OK' );
849 }
850
953c176d 851 #
055abad1 852 # Complex path with multiple non-capturing pathparts
853 # PathPart('') CaptureArgs(0), PathPart('foo') CaptureArgs(0), PathPart('') Args(0)
854 # should win over PathPart('') CaptureArgs(1), PathPart('') Args(0)
855 #
856 {
857 my @expected = qw[
858 TestApp::Controller::Action::Chained->begin
859 TestApp::Controller::Action::Chained->mult_nopp2_base
860 TestApp::Controller::Action::Chained->mult_nopp2_nocap
861 TestApp::Controller::Action::Chained->mult_nopp2_action
862 TestApp::Controller::Action::Chained->mult_nopp2_action_default
863 TestApp::Controller::Action::Chained->end
864 ];
865
866 my $expected = join( ", ", @expected );
867
868 ok( my $response = request('http://localhost/chained/mult_nopp2/action'),
869 "Complex path with multiple non-capturing pathparts" );
055abad1 870 is( $response->header('X-Catalyst-Executed'),
871 $expected, 'Executed actions' );
872 is( $response->content, '; ', 'Content OK' );
055abad1 873 }
874
875 #
953c176d 876 # Higher Args() hiding more specific CaptureArgs chains sections
877 #
878 {
879 my @expected = qw[
880 TestApp::Controller::Action::Chained->begin
881 TestApp::Controller::Action::Chained->cc_base
882 TestApp::Controller::Action::Chained->cc_link
883 TestApp::Controller::Action::Chained->cc_anchor
884 TestApp::Controller::Action::Chained->end
885 ];
886
887 my $expected = join ', ', @expected;
888
889 ok( my $response = request('http://localhost/chained/choose_capture/anchor.html'),
890 'Choose between an early Args() and a later more ideal chain' );
891 is( $response->header('X-Catalyst-Executed') => $expected, 'Executed actions');
892 is( $response->content => '; ', 'Content OK' );
893 }
894
895 #
896 # Less specific chain not being seen correctly due to earlier looser capture
897 #
898 {
899 my @expected = qw[
900 TestApp::Controller::Action::Chained->begin
901 TestApp::Controller::Action::Chained->cc_base
902 TestApp::Controller::Action::Chained->cc_b
903 TestApp::Controller::Action::Chained->cc_b_link
904 TestApp::Controller::Action::Chained->cc_b_anchor
905 TestApp::Controller::Action::Chained->end
906 ];
907
908 my $expected = join ', ', @expected;
909
910 ok( my $response = request('http://localhost/chained/choose_capture/b/a/anchor.html'),
911 'Choose between a more specific chain and an earlier looser one' );
912 is( $response->header('X-Catalyst-Executed') => $expected, 'Executed actions');
913 is( $response->content => 'a; ', 'Content OK' );
914 }
915
916 #
917 # Check we get the looser one when it's the correct match
918 #
919 {
920 my @expected = qw[
921 TestApp::Controller::Action::Chained->begin
922 TestApp::Controller::Action::Chained->cc_base
923 TestApp::Controller::Action::Chained->cc_a
924 TestApp::Controller::Action::Chained->cc_a_link
925 TestApp::Controller::Action::Chained->cc_a_anchor
926 TestApp::Controller::Action::Chained->end
927 ];
928
929 my $expected = join ', ', @expected;
930
931 ok( my $response = request('http://localhost/chained/choose_capture/a/a/anchor.html'),
932 'Choose between a more specific chain and an earlier looser one' );
933 is( $response->header('X-Catalyst-Executed') => $expected, 'Executed actions');
934 is( $response->content => 'a; anchor.html', 'Content OK' );
935 }
936
fd91d0c6 937 # CaptureArgs(1) PathPart('...') should win over CaptureArgs(2) PathPart('')
938 {
939 my @expected = qw[
940 TestApp::Controller::Action::Chained->begin
941 TestApp::Controller::Action::Chained::CaptureArgs->base
942 TestApp::Controller::Action::Chained::CaptureArgs->one_arg
943 TestApp::Controller::Action::Chained::CaptureArgs->edit_one_arg
944 TestApp::Controller::Action::Chained::CaptureArgs->end
945 ];
946
947 my $expected = join( ", ", @expected );
948
949 # should dispatch to /base/one_args/edit_one_arg
950 ok( my $response = request('http://localhost/captureargs/one/edit'),
951 'Correct arg order ran' );
ad9c323c 952 TODO: {
953 local $TODO = 'Known bug';
fd91d0c6 954 is( $response->header('X-Catalyst-Executed'),
955 $expected, 'Executed actions' );
956 is( $response->content, 'base; one_arg; edit_one_arg', 'Content OK' );
ad9c323c 957 }
fd91d0c6 958 }
959
1c24a6c4 960 # PathPart('...') Args(1) should win over CaptureArgs(2) PathPart('')
961 {
962 my @expected = qw[
963 TestApp::Controller::Action::Chained->begin
964 TestApp::Controller::Action::Chained::CaptureArgs->base
965 TestApp::Controller::Action::Chained::CaptureArgs->test_one_arg
966 TestApp::Controller::Action::Chained::CaptureArgs->end
967 ];
968
969 my $expected = join( ", ", @expected );
970
971 # should dispatch to /base/test_one_arg
972 ok( my $response = request('http://localhost/captureargs/test/one'),
973 'Correct pathpart/arg ran' );
974 TODO: {
975 local $TODO = 'Known bug';
976 is( $response->header('X-Catalyst-Executed'),
977 $expected, 'Executed actions' );
978 is( $response->content, 'base; test_plus_arg; one;', 'Content OK' );
979 }
980 }
981
953c176d 982 #
983 # Args(0) should win over Args() if we actually have no arguments.
984 {
985 my @expected = qw[
986 TestApp::Controller::Action::Chained->begin
987 TestApp::Controller::Action::Chained::ArgsOrder->base
988 TestApp::Controller::Action::Chained::ArgsOrder->index
989 TestApp::Controller::Action::Chained::ArgsOrder->end
990 ];
991
992 my $expected = join( ", ", @expected );
993
994 # With no args, we should run "index"
995 ok( my $response = request('http://localhost/argsorder/'),
996 'Correct arg order ran' );
997 is( $response->header('X-Catalyst-Executed'),
998 $expected, 'Executed actions' );
999 is( $response->content, 'base; ; index; ', 'Content OK' );
1000
1001 # With args given, run "all"
1002 ok( $response = request('http://localhost/argsorder/X'),
1003 'Correct arg order ran' );
1004 is( $response->header('X-Catalyst-Executed'),
1005 join(", ",
1006 qw[
1007 TestApp::Controller::Action::Chained->begin
1008 TestApp::Controller::Action::Chained::ArgsOrder->base
1009 TestApp::Controller::Action::Chained::ArgsOrder->all
1010 TestApp::Controller::Action::Chained::ArgsOrder->end
1011 ])
1012 );
1013 is( $response->content, 'base; ; all; X', 'Content OK' );
1014
1015 }
6365b527 1016
2f381252 1017 #
1018 # PathPrefix
1019 #
1020 {
1021 my @expected = qw[
1022 TestApp::Controller::Action::Chained->begin
1023 TestApp::Controller::Action::Chained::PathPrefix->instance
1024 TestApp::Controller::Action::Chained->end
1025 ];
1026
1027 my $expected = join( ", ", @expected );
1028
1029 ok( my $response = request('http://localhost/action/chained/pathprefix/1'),
1030 "PathPrefix (as an endpoint)" );
1031 is( $response->header('X-Catalyst-Executed'),
1032 $expected, 'Executed actions' );
1033 is( $response->content, '; 1', 'Content OK' );
1034 }
1035
1036 #
1037 # static paths vs. captures
1038 #
1039 {
1040 my @expected = qw[
1041 TestApp::Controller::Action::Chained->begin
1042 TestApp::Controller::Action::Chained->apan
1043 TestApp::Controller::Action::Chained->korv
1044 TestApp::Controller::Action::Chained->static_end
1045 TestApp::Controller::Action::Chained->end
1046 ];
1047
1048 my $expected = join( ", ", @expected );
1049
1050 ok( my $response = request('http://localhost/action/chained/static_end'),
1051 "static paths are prefered over captures" );
1052 is( $response->header('X-Catalyst-Executed'),
1053 $expected, 'Executed actions' );
1054 }
ef5e5ed1 1055
1056 #
1057 # */search
1058 # doc/*
1059 #
1060 # request for doc/search should end up in doc/*
1061 {
1062 my @expected = qw[
1063 TestApp::Controller::Action::Chained->begin
1064 TestApp::Controller::Action::Chained->doc_star
1065 TestApp::Controller::Action::Chained->end
1066 ];
1067
1068 my $expected = join( ", ", @expected );
1069
1070 ok( my $response = request('http://localhost/chained/doc/search'),
1071 "we prefer static path parts earlier in the chain" );
fc38b056 1072 TODO: {
1073 local $TODO = 'gbjk never got off his ass and fixed this';
1074 is( $response->header('X-Catalyst-Executed'),
1075 $expected, 'Executed actions' );
1076 }
ef5e5ed1 1077 }
2c527b91 1078
1079 {
1080 ok( my $content =
06f97d3f 1081 get('http://localhost/chained/capture%2Farg%3B/return_arg/foo%2Fbar%3B'),
2c527b91 1082 'request with URI-encoded arg' );
634780e0 1083 like( $content, qr{foo/bar;\z}, 'args decoded' );
06f97d3f 1084 like( $content, qr{capture/arg;}, 'captureargs decoded' );
2c527b91 1085 }
372b0c1b 1086 {
1087 ok( my $content =
1088 get('http://localhost/chained/return_arg_decoded/foo%2Fbar%3B'),
1089 'request with URI-encoded arg' );
1090 like( $content, qr{foo/bar;\z}, 'args decoded' );
1091 }
60dadd31 1092
36c67dc1 1093 # Test round tripping, specifically the / character %2F in uri_for:
a76d2786 1094 # not being able to feed it back action + captureargs and args into uri for
1095 # and result in the original request uri is a major piece of suck ;)
36c67dc1 1096 foreach my $thing (
1097 ['foo', 'bar'],
1098 ['foo%2Fbar', 'baz'],
1099 ['foo', 'bar%2Fbaz'],
1100 ['foo%2Fbar', 'baz%2Fquux'],
1101 ['foo%2Fbar', 'baz%2Fquux', { foo => 'bar', 'baz' => 'quux%2Ffrood'}],
1102 ['foo%2Fbar', 'baz%2Fquux', { foo => 'bar', 'baz%2Ffnoo' => 'quux%2Ffrood'}],
7b346bc3 1103 ['h%C3%BCtte', 'h%C3%BCtte', { test => 'h%C3%BCtte' } ],
36c67dc1 1104 ) {
9b7d26c7 1105 my $path = '/chained/roundtrip_urifor/' .
a76d2786 1106 $thing->[0] . '/' . $thing->[1];
9b7d26c7 1107 $path .= '?' . join('&',
a76d2786 1108 map { $_ .'='. $thing->[2]->{$_}}
1109 sort keys %{$thing->[2]}) if $thing->[2];
36c67dc1 1110 ok( my $content =
9b7d26c7 1111 get('http://localhost/' . $path),
1112 'request ' . $path . ' ok');
3aea242a 1113 my $exp = URI->new('http://localhost:3000' . $path);
8c756ee1 1114 my ($want) = $content =~ m{/chained/(.*)};
1115 my $got = URI->new('http://localhost:3000/chained/' . $want);
9b7d26c7 1116 # Just check that the path matches, as who the hell knows or cares
1117 # where the app is based (live tests etc)
3aea242a 1118 is $got->path, $exp->path, "uri $path can round trip through uri_for (path)"
1119 or diag("Expected $path, got $content");
d527814d 1120 is_deeply $got->query_form_hash, $exp->query_form_hash, "uri $path can round trip through uri_for (query)"
2689f8a4 1121 or diag("Expected $path, got $content");
36c67dc1 1122 }
1279064a 1123
1124 #
1125 # match_captures
1126 #
1127 {
1128
1129 ok( my $response = request('http://localhost/chained/match_captures/foo/bar'), 'match_captures: falling through' );
1130 is($response->header('X-TestAppActionTestMatchCaptures'), 'fallthrough', 'match_captures: fell through');
1131
1132 ok($response = request('http://localhost/chained/match_captures/force/bar'), 'match_captures: *not* falling through' );
1133 is($response->header('X-TestAppActionTestMatchCaptures'), 'forcing', 'match_captures: forced');
1134 is($response->header('X-TestAppActionTestMatchCapturesHasRan'), 'yes', 'match_captures: actually ran');
1135 }
141459fa 1136}
372b0c1b 1137
36c67dc1 1138done_testing;
a76d2786 1139