fix init_meta order when multiple also package are specified
[gitmo/Moose.git] / t / metaclasses / moose_exporter.t
index 3635a8b..fd0d9ea 100644 (file)
@@ -5,6 +5,7 @@ use warnings;
 
 use Test::More;
 use Test::Fatal;
+use Test::Moose;
 
 use Test::Requires {
     'Test::Output' => '0.01', # skip all if not installed
@@ -273,17 +274,16 @@ use Test::Requires {
 
 {
     package MooseX::OverridingSugar::PassThru;
-    
+
     sub with {
         my $caller = shift->name;
         return $caller . ' called with';
     }
-    
+
     Moose::Exporter->setup_import_methods(
         with_meta => ['with'],
         also      => 'MooseX::OverridingSugar',
     );
-    
 }
 
 {
@@ -416,4 +416,266 @@ use Test::Requires {
         for qw( with_meta1 with_meta2 with_caller1 with_caller2 as_is1 );
 }
 
+{
+    package InitMetaError;
+    use Moose::Exporter;
+    use Moose ();
+    Moose::Exporter->setup_import_methods(also => ['Moose']);
+    sub init_meta {
+        my $package = shift;
+        my %options = @_;
+        Moose->init_meta(%options, metaclass => 'Not::Loaded');
+    }
+}
+
+{
+    package InitMetaError::Role;
+    use Moose::Exporter;
+    use Moose::Role ();
+    Moose::Exporter->setup_import_methods(also => ['Moose::Role']);
+    sub init_meta {
+        my $package = shift;
+        my %options = @_;
+        Moose::Role->init_meta(%options, metaclass => 'Not::Loaded');
+    }
+}
+
+{
+    package WantsInvalidMetaclass;
+    ::like(
+        ::exception { InitMetaError->import },
+        qr/The Metaclass Not::Loaded must be loaded\. \(Perhaps you forgot to 'use Not::Loaded'\?\)/,
+        "error when wanting a nonexistent metaclass"
+    );
+}
+
+{
+    package WantsInvalidMetaclass::Role;
+    ::like(
+        ::exception { InitMetaError::Role->import },
+        qr/The Metaclass Not::Loaded must be loaded\. \(Perhaps you forgot to 'use Not::Loaded'\?\)/,
+        "error when wanting a nonexistent metaclass"
+    );
+}
+
+{
+    my @init_metas_called;
+
+    BEGIN {
+        package MultiLevelExporter1;
+        use Moose::Exporter;
+
+        sub foo  { 1 }
+        sub bar  { 1 }
+        sub baz  { 1 }
+        sub quux { 1 }
+
+        Moose::Exporter->setup_import_methods(
+            with_meta => [qw(foo bar baz quux)],
+        );
+
+        sub init_meta {
+            push @init_metas_called, 1;
+        }
+
+        $INC{'MultiLevelExporter1.pm'} = __FILE__;
+    }
+
+    BEGIN {
+        package MultiLevelExporter2;
+        use Moose::Exporter;
+
+        sub bar  { 2 }
+        sub baz  { 2 }
+        sub quux { 2 }
+
+        Moose::Exporter->setup_import_methods(
+            also      => ['MultiLevelExporter1'],
+            with_meta => [qw(bar baz quux)],
+        );
+
+        sub init_meta {
+            push @init_metas_called, 2;
+        }
+
+        $INC{'MultiLevelExporter2.pm'} = __FILE__;
+    }
+
+    BEGIN {
+        package MultiLevelExporter3;
+        use Moose::Exporter;
+
+        sub baz  { 3 }
+        sub quux { 3 }
+
+        Moose::Exporter->setup_import_methods(
+            also      => ['MultiLevelExporter2'],
+            with_meta => [qw(baz quux)],
+        );
+
+        sub init_meta {
+            push @init_metas_called, 3;
+        }
+
+        $INC{'MultiLevelExporter3.pm'} = __FILE__;
+    }
+
+    BEGIN {
+        package MultiLevelExporter4;
+        use Moose::Exporter;
+
+        sub quux { 4 }
+
+        Moose::Exporter->setup_import_methods(
+            also      => ['MultiLevelExporter3'],
+            with_meta => [qw(quux)],
+        );
+
+        sub init_meta {
+            push @init_metas_called, 4;
+        }
+
+        $INC{'MultiLevelExporter4.pm'} = __FILE__;
+    }
+
+    BEGIN { @init_metas_called = () }
+    {
+        package UsesMulti1;
+        use Moose;
+        use MultiLevelExporter1;
+        ::is(foo(), 1);
+        ::is(bar(), 1);
+        ::is(baz(), 1);
+        ::is(quux(), 1);
+    }
+    use Data::Dumper;
+    BEGIN { is_deeply(\@init_metas_called, [ 1 ]) || diag(Dumper(\@init_metas_called)) }
+
+    BEGIN { @init_metas_called = () }
+    {
+        package UsesMulti2;
+        use Moose;
+        use MultiLevelExporter2;
+        ::is(foo(), 1);
+        ::is(bar(), 2);
+        ::is(baz(), 2);
+        ::is(quux(), 2);
+    }
+    BEGIN { is_deeply(\@init_metas_called, [ 2, 1 ]) || diag(Dumper(\@init_metas_called)) }
+
+    BEGIN { @init_metas_called = () }
+    {
+        package UsesMulti3;
+        use Moose;
+        use MultiLevelExporter3;
+        ::is(foo(), 1);
+        ::is(bar(), 2);
+        ::is(baz(), 3);
+        ::is(quux(), 3);
+    }
+    BEGIN { is_deeply(\@init_metas_called, [ 3, 2, 1 ]) || diag(Dumper(\@init_metas_called)) }
+
+    BEGIN { @init_metas_called = () }
+    {
+        package UsesMulti4;
+        use Moose;
+        use MultiLevelExporter4;
+        ::is(foo(), 1);
+        ::is(bar(), 2);
+        ::is(baz(), 3);
+        ::is(quux(), 4);
+    }
+    BEGIN { is_deeply(\@init_metas_called, [ 4, 3, 2, 1 ]) || diag(Dumper(\@init_metas_called)) }
+}
+
+# Using "also => [ 'MooseX::UsesAlsoMoose', 'MooseX::SomethingElse' ]" should
+# continue to work. The init_meta order needs to be MooseX::CurrentExporter,
+# MooseX::UsesAlsoMoose, Moose, MooseX::SomethingElse. This is a pretty ugly
+# and messed up use case, but necessary until we come up with a better way to
+# do it.
+
+{
+    my @init_metas_called;
+
+    BEGIN {
+        package AlsoTest::Role1;
+        use Moose::Role;
+
+        $INC{'AlsoTest/Role1.pm'} = __FILE__;
+    }
+
+    BEGIN {
+        package AlsoTest1;
+        use Moose::Exporter;
+
+        Moose::Exporter->setup_import_methods(
+            also => [ 'Moose' ],
+        );
+
+        sub init_meta {
+            shift;
+            my %opts = @_;
+            ::ok(!Class::MOP::class_of($opts{for_class}));
+            push @init_metas_called, 1;
+        }
+
+        $INC{'AlsoTest1.pm'} = __FILE__;
+    }
+
+    BEGIN {
+        package AlsoTest2;
+        use Moose::Exporter;
+        use Moose::Util::MetaRole ();
+
+        Moose::Exporter->setup_import_methods;
+
+        sub init_meta {
+            shift;
+            my %opts = @_;
+            ::ok(Class::MOP::class_of($opts{for_class}));
+            Moose::Util::MetaRole::apply_metaroles(
+                for => $opts{for_class},
+                class_metaroles => {
+                    class => ['AlsoTest::Role1'],
+                },
+            );
+            push @init_metas_called, 2;
+        }
+
+        $INC{'AlsoTest2.pm'} = __FILE__;
+    }
+
+    BEGIN {
+        package AlsoTest3;
+        use Moose::Exporter;
+
+        Moose::Exporter->setup_import_methods(
+            also => [ 'AlsoTest1', 'AlsoTest2' ],
+        );
+
+        sub init_meta {
+            shift;
+            my %opts = @_;
+            ::ok(!Class::MOP::class_of($opts{for_class}));
+            push @init_metas_called, 3;
+        }
+
+        $INC{'AlsoTest3.pm'} = __FILE__;
+    }
+
+    BEGIN { @init_metas_called = () }
+    {
+        package UsesAlsoTest3;
+        use AlsoTest3;
+    }
+    use Data::Dumper;
+    BEGIN {
+        is_deeply(\@init_metas_called, [ 3, 1, 2 ])
+            || diag(Dumper(\@init_metas_called));
+        isa_ok(Class::MOP::class_of('UsesAlsoTest3'), 'Moose::Meta::Class');
+        does_ok(Class::MOP::class_of('UsesAlsoTest3'), 'AlsoTest::Role1');
+    }
+
+}
+
 done_testing;