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