More tests for ChildOf
Matt S Trout [Thu, 22 Jun 2006 14:50:28 +0000 (14:50 +0000)]
r10003@cain (orig r4367):  phaylon | 2006-06-11 19:39:13 +0000

t/lib/TestApp/Controller/Action/ChildOf.pm
t/lib/TestApp/Controller/Action/ChildOf/Bar.pm [new file with mode: 0644]
t/lib/TestApp/Controller/Action/ChildOf/Foo.pm
t/live_component_controller_action_childof.t

index 377c3d8..8370582 100644 (file)
@@ -7,26 +7,72 @@ use base qw/Catalyst::Controller/;
 
 sub begin :Private { }
 
+#
+#   Simple parent/child action test
+#
 sub foo  :PathPart('childof/foo')  :Captures(1) :ChildOf('/') { }
-sub foo2 :PathPart('childof/foo2') :Captures(2) :ChildOf('/') { }
-
-sub bar :PathPart('childof/bar') :ChildOf('/') { }
-
 sub endpoint  :PathPart('end')  :ChildOf('/action/childof/foo')  :Args(1) { }
+
+#
+#   Parent/child test with two args each
+#
+sub foo2 :PathPart('childof/foo2') :Captures(2) :ChildOf('/') { }
 sub endpoint2 :PathPart('end2') :ChildOf('/action/childof/foo2') :Args(2) { }
 
+#
+#   Relative specification of parent action
+#
+sub bar :PathPart('childof/bar') :ChildOf('/') { }
 sub finale :ChildOf('bar') :Args { }
 
+#
+#   three chain with concurrent endpoints
+#
 sub one   :PathPart('childof/one') :ChildOf('/')                   :Captures(1) { }
 sub two   :PathPart('two')         :ChildOf('/action/childof/one') :Captures(2) { }
-
 sub three_end :PathPart('three')       :ChildOf('two') :Args(3) { }
 sub one_end   :PathPart('childof/one') :ChildOf('/')   :Args(1) { }
 sub two_end   :PathPart('two')         :ChildOf('one') :Args(2) { }
 
+#
+#   Dispatch on number of arguments
+#
 sub multi1 :PathPart('childof/multi') :ChildOf('/') :Args(1) { }
 sub multi2 :PathPart('childof/multi') :ChildOf('/') :Args(2) { }
 
+#
+#   Roots in an action defined in a higher controller
+#
+sub higher_root :PathPart('bar') :ChildOf('/action/childof/foo/higher_root') :Args(1) { }
+
+#
+#   Controller -> subcontroller -> controller
+#
+sub pcp1 :PathPart('childof/pcp1')  :ChildOf('/')                        :Captures(1) { }
+sub pcp3 :PathPart                  :ChildOf('/action/childof/foo/pcp2') :Args(1)     { }
+
+#
+#   Dispatch on capture number
+#
+sub multi_cap1 :PathPart('childof/multi_cap') :ChildOf('/') :Captures(1) { }
+sub multi_cap2 :PathPart('childof/multi_cap') :ChildOf('/') :Captures(2) { }
+sub multi_cap_end1 :PathPart('baz') :ChildOf('multi_cap1') :Args(0) { }
+sub multi_cap_end2 :PathPart('baz') :ChildOf('multi_cap2') :Args(0) { }
+
+#
+#   Priority: Slurpy args vs. chained actions
+#
+sub priority_a1 :PathPart('childof/priority_a') :ChildOf('/') :Args { }
+sub priority_a2 :PathPart('childof/priority_a') :ChildOf('/') :Captures(1) { }
+sub priority_a2_end :PathPart('end') :ChildOf('priority_a2') :Args(1) { }
+
+#
+#   Priority: Fixed args vs. chained actions
+#
+sub priority_b1 :PathPart('childof/priority_b') :ChildOf('/') :Args(3) { }
+sub priority_b2 :PathPart('childof/priority_b') :ChildOf('/') :Captures(1) { }
+sub priority_b2_end :PathPart('end') :ChildOf('priority_b2') :Args(1) { }
+
 sub end :Private {
   my ($self, $c) = @_;
   my $out = join('; ', map { join(', ', @$_) }
diff --git a/t/lib/TestApp/Controller/Action/ChildOf/Bar.pm b/t/lib/TestApp/Controller/Action/ChildOf/Bar.pm
new file mode 100644 (file)
index 0000000..f83a882
--- /dev/null
@@ -0,0 +1,14 @@
+package TestApp::Controller::Action::ChildOf::Bar;
+
+use strict;
+use warnings;
+
+use base qw/Catalyst::Controller/;
+
+#
+#   Redispatching between controllers that are not in a parent/child
+#   relation. This is the root.
+#
+sub cross1 :PathPart('childof/cross') :Captures(1) :ChildOf('/') { }
+
+1;
index ffba0b3..1e1ea0a 100644 (file)
@@ -5,6 +5,24 @@ use warnings;
 
 use base qw/Catalyst::Controller/;
 
+#
+#   Child of current namespace
+#
 sub spoon :PathPart :ChildOf('') :Args(0) { }
 
+#
+#   Root for a action in a "parent" controller
+#
+sub higher_root :PathPart('childof/higher_root') :ChildOf('/') :Captures(1) { }
+
+#
+#   Parent controller -> this subcontroller -> parent controller test
+#
+sub pcp2 :PathPart :ChildOf('/action/childof/pcp1') :Captures(1) { }
+
+#
+#   Controllers not in parent/child relation. This tests the end.
+#
+sub cross2 :PathPart('end') :ChildOf('/action/childof/bar/cross1') :Args(1) { }
+
 1;
index 4e1de89..384f849 100644 (file)
@@ -10,7 +10,7 @@ our $iters;
 
 BEGIN { $iters = $ENV{CAT_BENCH_ITERS} || 2; }
 
-use Test::More tests => 27*$iters;
+use Test::More tests => 54*$iters;
 use Catalyst::Test 'TestApp';
 
 if ( $ENV{CAT_BENCHMARK} ) {
@@ -24,6 +24,11 @@ else {
 }
 
 sub run_tests {
+
+    #
+    #   This is a simple test where the parent and child actions are
+    #   within the same controller.
+    #
     {
         my @expected = qw[
           TestApp::Controller::Action::ChildOf->begin
@@ -39,6 +44,24 @@ sub run_tests {
             $expected, 'Executed actions' );
         is( $response->content, '1; 2', 'Content OK' );
     }
+
+    #
+    #   This makes sure the above isn't found if the argument for the
+    #   end action isn't supplied.
+    #
+    {
+        my $expected = undef;
+
+        ok( my $response = request('http://localhost/childof/foo/1/end'), 
+            'childof + local endpoint; missing last argument' );
+        is( $response->header('X-Catalyst-Executed'),
+            $expected, 'Executed actions' );
+        is( $response->header('Status'), 500, 'Status OK' );
+    }
+
+    #
+    #   Tests the case when the child action is placed in a subcontroller.
+    #
     {
         my @expected = qw[
           TestApp::Controller::Action::ChildOf->begin
@@ -54,6 +77,11 @@ sub run_tests {
             $expected, 'Executed actions' );
         is( $response->content, '1; ', 'Content OK' );
     }
+
+    #
+    #   Tests if the relative specification (e.g.: ChildOf('bar') ) works
+    #   as expected.
+    #
     {
         my @expected = qw[
           TestApp::Controller::Action::ChildOf->begin
@@ -69,6 +97,10 @@ sub run_tests {
             $expected, 'Executed actions' );
         is( $response->content, '; 1, spoon', 'Content OK' );
     }
+
+    #
+    #   Just a test for multiple arguments.
+    #
     {
         my @expected = qw[
           TestApp::Controller::Action::ChildOf->begin
@@ -85,6 +117,12 @@ sub run_tests {
             $expected, 'Executed actions' );
         is( $response->content, '10, 20; 15, 25', 'Content OK' );
     }
+
+    #
+    #   The first three-chain test tries to call the action with :Args(1)
+    #   specification. There's also a one action with a :Captures(1)
+    #   attribute, that should not be dispatched to.
+    #
     {
         my @expected = qw[
           TestApp::Controller::Action::ChildOf->begin
@@ -100,6 +138,12 @@ sub run_tests {
             $expected, 'Executed actions' );
         is( $response->content, '; 23', 'Content OK' );
     }
+
+    #
+    #   This is the second three-chain test, it goes for the action that
+    #   handles "/one/$cap/two/$arg1/$arg2" paths. Should be the two action
+    #   having :Args(2), not the one having :Captures(2).
+    #
     {
         my @expected = qw[
           TestApp::Controller::Action::ChildOf->begin
@@ -116,6 +160,12 @@ sub run_tests {
             $expected, 'Executed actions' );
         is( $response->content, '23; 23, 46', 'Content OK' );
     }
+
+    #
+    #   Last of the three-chain tests. Has no concurrent action with :Captures
+    #   and is more thought to simply test the chain as a whole and the 'two'
+    #   action specifying :Captures.
+    #
     {
         my @expected = qw[
           TestApp::Controller::Action::ChildOf->begin
@@ -133,6 +183,11 @@ sub run_tests {
             $expected, 'Executed actions' );
         is( $response->content, '23, 23, 46; 1, 2, 3', 'Content OK' );
     }
+
+    #
+    #   Tests dispatching on number of arguments for :Args. This should be
+    #   dispatched to the action expecting one argument.
+    #
     {
         my @expected = qw[
           TestApp::Controller::Action::ChildOf->begin
@@ -148,6 +203,10 @@ sub run_tests {
             $expected, 'Executed actions' );
         is( $response->content, '; 23', 'Content OK' );
     }
+
+    #
+    #   Belongs to the former test and goes for the action expecting two arguments.
+    #
     {
         my @expected = qw[
           TestApp::Controller::Action::ChildOf->begin
@@ -163,4 +222,165 @@ sub run_tests {
             $expected, 'Executed actions' );
         is( $response->content, '; 23, 46', 'Content OK' );
     }
+
+    #
+    #   Dispatching on argument count again, this time we provide too many
+    #   arguments, so dispatching should fail.
+    #
+    {
+        my $expected = undef;
+
+        ok( my $response = request('http://localhost/childof/multi/23/46/67'),
+            'multi-action (three args, should lead to error)' );
+        is( $response->header('X-Catalyst-Executed'),
+            $expected, 'Executed actions' );
+        is( $response->header('Status'), 500, 'Status OK' );
+    }
+
+    #
+    #   This tests the case when an action says it's the child of an action in
+    #   a subcontroller.
+    #
+    {
+        my @expected = qw[
+          TestApp::Controller::Action::ChildOf->begin
+          TestApp::Controller::Action::ChildOf::Foo->higher_root
+          TestApp::Controller::Action::ChildOf->higher_root
+          TestApp::Controller::Action::ChildOf->end
+        ];
+
+        my $expected = join( ", ", @expected );
+
+        ok( my $response = request('http://localhost/childof/higher_root/23/bar/11'),
+            'root higher than child' );
+        is( $response->header('X-Catalyst-Executed'),
+            $expected, 'Executed actions' );
+        is( $response->content, '23; 11', 'Content OK' );
+    }
+
+    #
+    #   Just a more complex version of the former test. It tests if a controller ->
+    #   subcontroller -> controller dispatch works.
+    #
+    {
+        my @expected = qw[
+          TestApp::Controller::Action::ChildOf->begin
+          TestApp::Controller::Action::ChildOf->pcp1
+          TestApp::Controller::Action::ChildOf::Foo->pcp2
+          TestApp::Controller::Action::ChildOf->pcp3
+          TestApp::Controller::Action::ChildOf->end
+        ];
+
+        my $expected = join( ", ", @expected );
+
+        ok( my $response = request('http://localhost/childof/pcp1/1/pcp2/2/pcp3/3'),
+            'parent -> child -> parent' );
+        is( $response->header('X-Catalyst-Executed'),
+            $expected, 'Executed actions' );
+        is( $response->content, '1, 2; 3', 'Content OK' );
+    }
+
+    #
+    #   Tests dispatch on capture number. This test is for a one capture action.
+    #
+    {
+        my @expected = qw[
+          TestApp::Controller::Action::ChildOf->begin
+          TestApp::Controller::Action::ChildOf->multi_cap1
+          TestApp::Controller::Action::ChildOf->multi_cap_end1
+          TestApp::Controller::Action::ChildOf->end
+        ];
+
+        my $expected = join( ", ", @expected );
+
+        ok( my $response = request('http://localhost/childof/multi_cap/1/baz'),
+            'dispatch on capture num 1' );
+        is( $response->header('X-Catalyst-Executed'),
+            $expected, 'Executed actions' );
+        is( $response->content, '1; ', 'Content OK' );
+    }
+
+    #
+    #   Belongs to the former test. This one goes for the action expecting two
+    #   captures.
+    #
+    {
+        my @expected = qw[
+          TestApp::Controller::Action::ChildOf->begin
+          TestApp::Controller::Action::ChildOf->multi_cap2
+          TestApp::Controller::Action::ChildOf->multi_cap_end2
+          TestApp::Controller::Action::ChildOf->end
+        ];
+
+        my $expected = join( ", ", @expected );
+
+        ok( my $response = request('http://localhost/childof/multi_cap/1/2/baz'),
+            'dispatch on capture num 2' );
+        is( $response->header('X-Catalyst-Executed'),
+            $expected, 'Executed actions' );
+        is( $response->content, '1, 2; ', 'Content OK' );
+    }
+
+    #
+    #   Tests the priority of a slurpy arguments action (with :Args) against
+    #   two actions chained together. The two actions should win.
+    #
+    {
+        my @expected = qw[
+          TestApp::Controller::Action::ChildOf->begin
+          TestApp::Controller::Action::ChildOf->priority_a2
+          TestApp::Controller::Action::ChildOf->priority_a2_end
+          TestApp::Controller::Action::ChildOf->end
+        ];
+
+        my $expected = join( ", ", @expected );
+
+        ok( my $response = request('http://localhost/childof/priority_a/1/end/2'),
+            'priority - slurpy args vs. parent/child' );
+        is( $response->header('X-Catalyst-Executed'),
+            $expected, 'Executed actions' );
+        is( $response->content, '1; 2', 'Content OK' );
+    }
+
+    #
+    #   This belongs to the former test but tests if two chained actions have
+    #   priority over an action with the exact arguments.
+    #
+    {
+        my @expected = qw[
+          TestApp::Controller::Action::ChildOf->begin
+          TestApp::Controller::Action::ChildOf->priority_b2
+          TestApp::Controller::Action::ChildOf->priority_b2_end
+          TestApp::Controller::Action::ChildOf->end
+        ];
+
+        my $expected = join( ", ", @expected );
+
+        ok( my $response = request('http://localhost/childof/priority_b/1/end/2'),
+            'priority - fixed args vs. parent/child' );
+        is( $response->header('X-Catalyst-Executed'),
+            $expected, 'Executed actions' );
+        is( $response->content, '1; 2', 'Content OK' );
+    }
+
+    #
+    #   Test dispatching between two controllers that are on the same level and
+    #   therefor have no parent/child relationship.
+    #
+    {
+        my @expected = qw[
+          TestApp::Controller::Action::ChildOf->begin
+          TestApp::Controller::Action::ChildOf::Bar->cross1
+          TestApp::Controller::Action::ChildOf::Foo->cross2
+          TestApp::Controller::Action::ChildOf->end
+        ];
+
+        my $expected = join( ", ", @expected );
+
+        ok( my $response = request('http://localhost/childof/cross/1/end/2'),
+            'cross controller w/o par/child relation' );
+        is( $response->header('X-Catalyst-Executed'),
+            $expected, 'Executed actions' );
+        is( $response->content, '1; 2', 'Content OK' );
+    }
 }