first cut at :ChildOf
[catagits/Catalyst-Runtime.git] / t / unit_core_component_loading.t
1 # 2 initial tests, and 6 per component in the loop below
2 # (do not forget to update the number of components in test 3 as well)
3 # 4 extra tests for the loading options
4 use Test::More tests => 2 + 6 * 24 + 4;
5
6 use strict;
7 use warnings;
8
9 use File::Spec;
10 use File::Path;
11
12 my $libdir = 'test_trash';
13 unshift(@INC, $libdir);
14
15 my $appclass = 'TestComponents';
16 my @components = (
17     { type => 'Controller', prefix => 'C', name => 'Bar' },
18     { type => 'Controller', prefix => 'C', name => 'Foo::Bar' },
19     { type => 'Controller', prefix => 'C', name => 'Foo::Foo::Bar' },
20     { type => 'Controller', prefix => 'C', name => 'Foo::Foo::Foo::Bar' },
21     { type => 'Controller', prefix => 'Controller', name => 'Bar::Bar::Bar::Foo' },
22     { type => 'Controller', prefix => 'Controller', name => 'Bar::Bar::Foo' },
23     { type => 'Controller', prefix => 'Controller', name => 'Bar::Foo' },
24     { type => 'Controller', prefix => 'Controller', name => 'Foo' },
25     { type => 'Model', prefix => 'M', name => 'Bar' },
26     { type => 'Model', prefix => 'M', name => 'Foo::Bar' },
27     { type => 'Model', prefix => 'M', name => 'Foo::Foo::Bar' },
28     { type => 'Model', prefix => 'M', name => 'Foo::Foo::Foo::Bar' },
29     { type => 'Model', prefix => 'Model', name => 'Bar::Bar::Bar::Foo' },
30     { type => 'Model', prefix => 'Model', name => 'Bar::Bar::Foo' },
31     { type => 'Model', prefix => 'Model', name => 'Bar::Foo' },
32     { type => 'Model', prefix => 'Model', name => 'Foo' },
33     { type => 'View', prefix => 'V', name => 'Bar' },
34     { type => 'View', prefix => 'V', name => 'Foo::Bar' },
35     { type => 'View', prefix => 'V', name => 'Foo::Foo::Bar' },
36     { type => 'View', prefix => 'V', name => 'Foo::Foo::Foo::Bar' },
37     { type => 'View', prefix => 'View', name => 'Bar::Bar::Bar::Foo' },
38     { type => 'View', prefix => 'View', name => 'Bar::Bar::Foo' },
39     { type => 'View', prefix => 'View', name => 'Bar::Foo' },
40     { type => 'View', prefix => 'View', name => 'Foo' },
41 );
42
43 sub make_component_file {
44     my ($type, $prefix, $name) = @_;
45
46     my $compbase = "Catalyst::${type}";
47     my $fullname = "${appclass}::${prefix}::${name}";
48     my @namedirs = split(/::/, $name);
49     my $name_final = pop(@namedirs);
50     my @dir_list = ($libdir, $appclass, $prefix, @namedirs);
51     my $dir_ux   = join(q{/}, @dir_list);
52     my $dir      = File::Spec->catdir(@dir_list);
53     my $file     = File::Spec->catfile($dir, $name_final . '.pm');
54
55     mkpath($dir_ux); # mkpath wants unix '/' seperators :p
56     open(my $fh, '>', $file) or die "Could not open file $file for writing: $!";
57     print $fh <<EOF;
58 package $fullname;
59 use base '$compbase';
60 sub COMPONENT {
61     my \$self = shift->NEXT::COMPONENT(\@_);
62     no strict 'refs';
63     *{\__PACKAGE__ . "::whoami"} = sub { return \__PACKAGE__; };
64     \$self;
65 }
66 1;
67
68 EOF
69
70     close($fh);
71 }
72
73 foreach my $component (@components) {
74     make_component_file($component->{type},
75                         $component->{prefix},
76                         $component->{name});
77 }
78
79 eval "package $appclass; use Catalyst; __PACKAGE__->setup";
80
81 can_ok( $appclass, 'components');
82
83 my $complist = $appclass->components;
84
85 # the +1 below is for the app class itself
86 is(scalar keys %$complist, 24+1, "Correct number of components loaded");
87
88 foreach (keys %$complist) {
89
90     # Skip the component which happens to be the app itself
91     next if $_ eq $appclass;
92
93     my $instance = $appclass->component($_);
94     isa_ok($instance, $_);
95     can_ok($instance, 'whoami');
96     is($instance->whoami, $_);
97
98     if($_ =~ /^${appclass}::(?:V|View)::(.*)/) {
99         my $moniker = $1;
100         isa_ok($instance, 'Catalyst::View');
101         can_ok($appclass->view($moniker), 'whoami');
102         is($appclass->view($moniker)->whoami, $_);
103     }
104     elsif($_ =~ /^${appclass}::(?:M|Model)::(.*)/) {
105         my $moniker = $1;
106         isa_ok($instance, 'Catalyst::Model');
107         can_ok($appclass->model($moniker), 'whoami');
108         is($appclass->model($moniker)->whoami, $_);
109     }
110     elsif($_ =~ /^${appclass}::(?:C|Controller)::(.*)/) {
111         my $moniker = $1;
112         isa_ok($instance, 'Catalyst::Controller');
113         can_ok($appclass->controller($moniker), 'whoami');
114         is($appclass->controller($moniker)->whoami, $_);
115     }
116     else {
117         die "Something is wrong with this test, this should"
118             . " have been unreachable";
119     }
120 }
121
122 rmtree($libdir);
123
124 # test extra component loading options
125
126 $appclass = 'ExtraOptions';
127 push @components, { type => 'View', prefix => 'Extra', name => 'Foo' };
128
129 foreach my $component (@components) {
130     make_component_file($component->{type},
131                         $component->{prefix},
132                         $component->{name});
133 }
134
135 eval qq(
136 package $appclass;
137 use Catalyst;
138 __PACKAGE__->config->{ setup_components } = {
139     search_extra => [ '::Extra' ],
140     except       => [ "${appclass}::Controller::Foo" ]
141 };
142 __PACKAGE__->setup;
143 );
144
145 can_ok( $appclass, 'components');
146
147 $complist = $appclass->components;
148
149 is(scalar keys %$complist, 24+1, "Correct number of components loaded");
150
151 ok( !exists $complist->{ "${appclass}::Controller::Foo" }, 'Controller::Foo was skipped' );
152 ok( exists $complist->{ "${appclass}::Extra::Foo" }, 'Extra::Foo was loaded' );
153
154 rmtree($libdir);