1 # way too many tests to count
10 my $libdir = 'test_trash';
12 unshift(@INC, $libdir);
14 my $appclass = 'TestComponents';
16 { type => 'Controller', prefix => 'C', name => 'Bar' },
17 { type => 'Controller', prefix => 'C', name => 'Foo::Bar' },
18 { type => 'Controller', prefix => 'C', name => 'Foo::Foo::Bar' },
19 { type => 'Controller', prefix => 'C', name => 'Foo::Foo::Foo::Bar' },
20 { type => 'Controller', prefix => 'Controller', name => 'Bar::Bar::Bar::Foo' },
21 { type => 'Controller', prefix => 'Controller', name => 'Bar::Bar::Foo' },
22 { type => 'Controller', prefix => 'Controller', name => 'Bar::Foo' },
23 { type => 'Controller', prefix => 'Controller', name => 'Foo' },
24 { type => 'Model', prefix => 'M', name => 'Bar' },
25 { type => 'Model', prefix => 'M', name => 'Foo::Bar' },
26 { type => 'Model', prefix => 'M', name => 'Foo::Foo::Bar' },
27 { type => 'Model', prefix => 'M', name => 'Foo::Foo::Foo::Bar' },
28 { type => 'Model', prefix => 'Model', name => 'Bar::Bar::Bar::Foo' },
29 { type => 'Model', prefix => 'Model', name => 'Bar::Bar::Foo' },
30 { type => 'Model', prefix => 'Model', name => 'Bar::Foo' },
31 { type => 'Model', prefix => 'Model', name => 'Foo' },
32 { type => 'View', prefix => 'V', name => 'Bar' },
33 { type => 'View', prefix => 'V', name => 'Foo::Bar' },
34 { type => 'View', prefix => 'V', name => 'Foo::Foo::Bar' },
35 { type => 'View', prefix => 'V', name => 'Foo::Foo::Foo::Bar' },
36 { type => 'View', prefix => 'View', name => 'Bar::Bar::Bar::Foo' },
37 { type => 'View', prefix => 'View', name => 'Bar::Bar::Foo' },
38 { type => 'View', prefix => 'View', name => 'Bar::Foo' },
39 { type => 'View', prefix => 'View', name => 'Foo' },
42 sub write_component_file {
43 my ($dir_list, $module_name, $content) = @_;
45 my $dir = File::Spec->catdir(@$dir_list);
46 my $file = File::Spec->catfile($dir, $module_name . '.pm');
48 mkpath(join(q{/}, @$dir_list) );
49 open(my $fh, '>', $file) or die "Could not open file $file for writing: $!";
54 sub make_component_file {
55 my ($libdir, $appclass, $type, $prefix, $name) = @_;
57 my $compbase = "Catalyst::${type}";
58 my $fullname = "${appclass}::${prefix}::${name}";
59 my @namedirs = split(/::/, $name);
60 my $name_final = pop(@namedirs);
61 my @dir_list = ($libdir, $appclass, $prefix, @namedirs);
63 write_component_file(\@dir_list, $name_final, <<EOF);
68 my \$self = shift->next::method(\@_);
70 *{\__PACKAGE__ . "::whoami"} = sub { return \__PACKAGE__; };
78 foreach my $component (@components) {
88 my $shut_up_deprecated_warnings = q{
89 __PACKAGE__->log(Catalyst::Log->new('fatal'));
92 eval "package $appclass; use Catalyst; $shut_up_deprecated_warnings __PACKAGE__->setup";
95 [ sort $appclass->locate_components ],
96 [ map { $appclass . '::' . $_->{prefix} . '::' . $_->{name} } @components ], 'locate_components finds the components correctly'
99 can_ok( $appclass, 'components');
101 my $complist = $appclass->components;
103 # FIXME should the app class really be included in ->components?
104 # the +1 below is for the app class itself
105 is(scalar keys %$complist, 24+1, "Correct number of components loaded");
107 foreach (keys %$complist) {
109 # Skip the component which happens to be the app itself
110 next if $_ eq $appclass;
112 my $instance = $appclass->component($_);
113 isa_ok($instance, $_);
114 can_ok($instance, 'whoami');
115 is($instance->whoami, $_);
117 if($_ =~ /^${appclass}::(?:V|View)::(.*)/) {
119 isa_ok($instance, 'Catalyst::View');
120 can_ok($appclass->view($moniker), 'whoami');
121 is($appclass->view($moniker)->whoami, $_);
123 elsif($_ =~ /^${appclass}::(?:M|Model)::(.*)/) {
125 isa_ok($instance, 'Catalyst::Model');
126 can_ok($appclass->model($moniker), 'whoami');
127 is($appclass->model($moniker)->whoami, $_);
129 elsif($_ =~ /^${appclass}::(?:C|Controller)::(.*)/) {
131 isa_ok($instance, 'Catalyst::Controller');
132 can_ok($appclass->controller($moniker), 'whoami');
133 is($appclass->controller($moniker)->whoami, $_);
136 die "Something is wrong with this test, this should"
137 . " have been unreachable";
143 # test extra component loading options
145 $appclass = 'ExtraOptions';
146 push @components, { type => 'View', prefix => 'Extra', name => 'Foo' };
148 foreach my $component (@components) {
153 $component->{prefix},
161 $shut_up_deprecated_warnings
162 __PACKAGE__->config->{ setup_components } = {
163 search_extra => [ '::Extra' ],
164 except => [ "${appclass}::Controller::Foo" ]
171 search_extra => [ '::Extra' ],
172 except => [ "${appclass}::Controller::Foo" ]
174 my @components_located = $appclass->locate_components($config);
175 my @components_expected;
177 my $name = $appclass . '::' . $_->{prefix} . '::' . $_->{name};
178 push @components_expected, $name if $name ne "${appclass}::Controller::Foo";
181 [ sort @components_located ],
182 [ sort @components_expected ],
183 'locate_components finds the components correctly'
187 can_ok( $appclass, 'components');
189 $complist = $appclass->components;
191 is(scalar keys %$complist, 24+1, "Correct number of components loaded");
193 ok( !exists $complist->{ "${appclass}::Controller::Foo" }, 'Controller::Foo was skipped' );
194 ok( exists $complist->{ "${appclass}::Extra::Foo" }, 'Extra::Foo was loaded' );
198 $appclass = "ComponentOnce";
200 write_component_file([$libdir, $appclass, 'Model'], 'TopLevel', <<EOF);
201 package ${appclass}::Model::TopLevel;
202 use base 'Catalyst::Model';
205 my \$self = shift->next::method(\@_);
207 *{\__PACKAGE__ . "::whoami"} = sub { return \__PACKAGE__; };
208 *${appclass}::Model::TopLevel::GENERATED::ACCEPT_CONTEXT = sub {
209 return bless {}, 'FooBarBazQuux';
214 package ${appclass}::Model::TopLevel::Nested;
216 sub COMPONENT { die "COMPONENT called in the wrong order!"; }
222 write_component_file([$libdir, $appclass, 'Model', 'TopLevel'], 'Nested', <<EOF);
223 package ${appclass}::Model::TopLevel::Nested;
224 use base 'Catalyst::Model';
227 no warnings 'redefine';
228 sub COMPONENT { \$called++;return shift->next::method(\@_); }
229 sub called { return \$called };
234 eval "package $appclass; use Catalyst; __PACKAGE__->setup";
236 is($@, '', "Didn't load component twice");
237 is($appclass->model('TopLevel::Nested')->called,1, 'COMPONENT called once');
239 ok($appclass->model('TopLevel::GENERATED'), 'Have generated model');
240 is(ref($appclass->model('TopLevel::GENERATED')), 'FooBarBazQuux',
241 'ACCEPT_CONTEXT in generated inner package fired as expected');
243 $appclass = "InnerComponent";
246 package InnerComponent::Controller::Test;
247 use base 'Catalyst::Controller';
250 $INC{'InnerComponent/Controller/Test.pm'} = 1;
252 eval "package $appclass; use Catalyst; __PACKAGE__->setup";
254 isa_ok($appclass->controller('Test'), 'Catalyst::Controller');