merged
John Napiorkowski [Thu, 29 Oct 2015 15:13:48 +0000 (10:13 -0500)]
Changes
lib/Catalyst.pm
t/aggregate/unit_core_component_loading.t
t/aggregate/unit_core_uri_for.t
t/aggregate/unit_core_uri_for_action.t

diff --git a/Changes b/Changes
index 7853d3c..644e0f5 100644 (file)
--- a/Changes
+++ b/Changes
@@ -5,6 +5,8 @@
   - Fixed spurious warnings in uri_for when using no arguments (melmothx++ and 
     paultcochrane++)
   - Documentation improvements (paultcochrane++)
+  - Improvements to 'search_extra' configuration and tests around using 
+    uri_for as a class method (cngarrison++)
 
 5.90101 - 2015-09-04
   - Fixed a regression introduced in the last release which caused test
index d86c6f4..820fc35 100644 (file)
@@ -807,6 +807,11 @@ sub controller {
             my $comps = $c->components;
             my $check = $appclass."::Controller::".$name;
             return $c->_filter_component( $comps->{$check}, @args ) if exists $comps->{$check};
+            foreach my $path (@{$appclass->config->{ setup_components }->{ search_extra }}) {
+                next unless $path =~ /.*::Controller/;
+                $check = $path."::".$name;
+                return $c->_filter_component( $comps->{$check}, @args ) if exists $comps->{$check};
+            }
         }
         my @result = $c->_comp_search_prefixes( $name, qw/Controller C/ );
         return map { $c->_filter_component( $_, @args ) } @result if ref $name;
@@ -846,6 +851,11 @@ sub model {
             my $comps = $c->components;
             my $check = $appclass."::Model::".$name;
             return $c->_filter_component( $comps->{$check}, @args ) if exists $comps->{$check};
+            foreach my $path (@{$appclass->config->{ setup_components }->{ search_extra }}) {
+                next unless $path =~ /.*::Model/;
+                $check = $path."::".$name;
+                return $c->_filter_component( $comps->{$check}, @args ) if exists $comps->{$check};
+            }
         }
         my @result = $c->_comp_search_prefixes( $name, qw/Model M/ );
         return map { $c->_filter_component( $_, @args ) } @result if ref $name;
@@ -910,6 +920,11 @@ sub view {
             else {
                 $c->log->warn( "Attempted to use view '$check', but does not exist" );
             }
+            foreach my $path (@{$appclass->config->{ setup_components }->{ search_extra }}) {
+                next unless $path =~ /.*::View/;
+                $check = $path."::".$name;
+                return $c->_filter_component( $comps->{$check}, @args ) if exists $comps->{$check};
+            }
         }
         my @result = $c->_comp_search_prefixes( $name, qw/View V/ );
         return map { $c->_filter_component( $_, @args ) } @result if ref $name;
@@ -3090,7 +3105,7 @@ sub locate_components {
     my $config = shift;
 
     my @paths   = qw( ::M ::Model ::V ::View ::C ::Controller );
-    my $extra   = delete $config->{ search_extra } || [];
+    my $extra   = $config->{ search_extra } || [];
 
     unshift @paths, @$extra;
 
index 2c53144..a408dd7 100644 (file)
@@ -2,7 +2,7 @@
 # (do not forget to update the number of components in test 3 as well)
 # 5 extra tests for the loading options
 # One test for components in inner packages
-use Test::More tests => 2 + 6 * 24 + 8 + 1;
+use Test::More tests => 2 + 6 * 24 + 9 + 1;
 
 use strict;
 use warnings;
@@ -152,12 +152,20 @@ foreach my $component (@components) {
     );
 }
 
+    make_component_file(
+        $libdir,
+        'ExternalExtra',
+        'Controller',
+        'Controller',
+        'FooExternal',
+    );
+
 eval qq(
 package $appclass;
 use Catalyst;
 $shut_up_deprecated_warnings
 __PACKAGE__->config->{ setup_components } = {
-    search_extra => [ '::Extra' ],
+    search_extra => [ '::Extra', 'ExternalExtra::Controller' ],
     except       => [ "${appclass}::Controller::Foo" ]
 };
 __PACKAGE__->setup;
@@ -167,11 +175,13 @@ can_ok( $appclass, 'components');
 
 $complist = $appclass->components;
 
-is(scalar keys %$complist, 24+1, "Correct number of components loaded");
+is(scalar keys %$complist, 24+2, "Correct number of components loaded");
 
 ok( !exists $complist->{ "${appclass}::Controller::Foo" }, 'Controller::Foo was skipped' );
 ok( exists $complist->{ "${appclass}::Extra::Foo" }, 'Extra::Foo was loaded' );
 
+isa_ok($appclass->controller('FooExternal'), 'Catalyst::Controller', 'ExternalExtra::Controller::FooExternal was loaded');
+
 rmtree($libdir);
 
 $appclass = "ComponentOnce";
index 43f7d50..ab256f0 100644 (file)
@@ -83,6 +83,59 @@ is(
     'URI for path with fragment and query params 3'
 );
 
+is(
+    Catalyst::uri_for( 'TestApp', '/bar/baz' )->as_string,
+    '/bar/baz',
+    'URI for absolute path, called with only class name'
+);
+
+## relative action (or path) doesn't make sense when calling as class method
+# is(
+#     Catalyst::uri_for( 'TestApp', 'bar/baz' )->as_string,
+#     '/yada/bar/baz',
+#     'URI for relative path, called with only class name'
+# );
+
+is(
+    Catalyst::uri_for( 'TestApp', '/', 'arg1', 'arg2' )->as_string,
+    '/arg1/arg2',
+    'URI for root action with args, called with only class name'
+);
+
+## relative action (or path) doesn't make sense when calling as class method
+# is( Catalyst::uri_for( 'TestApp', '../quux' )->as_string,
+#     '/quux', 'URI for relative dot path, called with only class name' );
+
+is(
+    Catalyst::uri_for( 'TestApp', '/quux', { param1 => 'value1' } )->as_string,
+    '/quux?param1=value1',
+    'URI for quux action with query params, called with only class name'
+);
+
+is (Catalyst::uri_for( 'TestApp', '/bar/wibble?' )->as_string,
+   '/bar/wibble%3F', 'Question Mark gets encoded, called with only class name'
+);
+
+## relative action (or path) doesn't make sense when calling as class method
+# is( Catalyst::uri_for( 'TestApp', qw/bar wibble?/, 'with space' )->as_string,
+#     '/yada/bar/wibble%3F/with%20space', 'Space gets encoded, called with only class name'
+# );
+
+is(
+    Catalyst::uri_for( 'TestApp', '/bar', 'with+plus', { 'also' => 'with+plus' })->as_string,
+    '/bar/with+plus?also=with%2Bplus',
+    'Plus is not encoded, called with only class name'
+);
+
+TODO: {
+    local $TODO = 'broken by 5.7008';
+    is(
+        Catalyst::uri_for( $context, '/bar#fragment', { param1 => 'value1' } )->as_string,
+        'http://127.0.0.1/foo/bar?param1=value1#fragment',
+        'URI for path with fragment and query params'
+    );
+}
+
 # test with utf-8
 is(
     Catalyst::uri_for( $context, 'quux', { param1 => "\x{2620}" } )->as_string,
index 4036f88..7341365 100644 (file)
@@ -77,6 +77,36 @@ my $context = TestApp->new( {
                 namespace => 'yada',
               } );
 
+
+
+
+# this works, using $ctx
+is($context->uri_for( 'TestApp', $context->controller('Action::Chained')->action_for('endpoint')),
+   "http://127.0.0.1/foo/yada/chained/foo/end",
+   "uri_for a controller and action");
+
+# this fails, uri_for returns undef, why isn't this one working??
+is( $context->uri_for_action( '/action/chained/endpoint' ),
+       'http://127.0.0.1/chained/foo/end',
+   "uri_for a controller and action as string");
+
+# this fails, uri_for returns undef
+is(Catalyst::uri_for_action( 'TestApp', $context->controller('Action::Chained')->action_for('endpoint')),
+   "/chained/foo/end",
+   "uri_for a controller and action, called with only class name");
+
+# this fails, uri_for returns undef
+is(Catalyst::uri_for_action( 'TestApp', '/action/chained/endpoint' ),
+   "/chained/foo/end",
+   "uri_for a controller and action as string, called with only class name");
+
+# this fails, uri_for returns undef
+is(Catalyst::uri_for_action( 'TestApp', $chained_action),
+   "/chained/foo/end",
+   "uri_for action via dispatcher, called with only class name");
+
+
+
 is($context->uri_for($context->controller('Action')),
    "http://127.0.0.1/foo/yada/action/",
    "uri_for a controller");