Able to use strings rather than having to use hash refs
[catagits/CatalystX-DynamicComponent.git] / t / 03_dynamiccomponent.t
1 use strict;
2 use warnings;
3
4 use Test::More tests => 38;
5 use Test::Exception;
6
7 use Moose ();
8 BEGIN { use_ok('CatalystX::DynamicComponent') }
9
10 my $testapp_counter = 0;
11 sub generate_testapp {
12     my $role_options = shift || {};
13     my $meta = Moose->init_meta( for_class => "TestApp" . $testapp_counter++ );
14     $meta->superclasses('Catalyst');
15     Moose::Util::apply_all_roles($meta, 'CatalystX::DynamicComponent', $role_options);
16     $meta->name->setup;
17     return $meta;
18 }
19
20 throws_ok { generate_testapp(); }
21     qr/name\) is required/, 'name is required';
22
23 {
24     my $app_meta = generate_testapp({ name => 'dynamic_component_method' });
25     my $app = $app_meta->name;
26     ok $app->can('dynamic_component_method'), 'dynamic component method added';
27     $app->dynamic_component_method( "Model::Foo", {} );
28     my $foo = $app->model('Foo');
29     ok $foo, 'Have added Foo component';
30     isa_ok($foo, 'Catalyst::Component');
31 }
32
33 {
34     my $COMPONENT = sub { return bless {}, 'TestClass' };
35     my $app_meta = generate_testapp({
36         name => 'dynamic_component_method',
37         methods => {
38             COMPONENT => $COMPONENT,
39         },
40     });
41     my $app = $app_meta->name;
42     ok $app->can('dynamic_component_method'), 'dynamic component method added';
43     $app->dynamic_component_method( "Model::Foo", {} );
44     my $foo = $app->model('Foo');
45     ok $foo, 'Have added Foo component';
46     isa_ok($foo, 'TestClass', 'COMPONENT method returned totally different class');
47     my $name = $app . "::Model::Foo";
48     isa_ok(bless({}, $name), 'Catalyst::Component', 'Underlying $app::Model::Foo is a C::C');
49     is($name->can('COMPONENT'), $COMPONENT, 'Supplied COMPONENT method is on $app::Model::Foo');
50 }
51 {
52     package My::Other::Superclass;
53     use Moose;
54     __PACKAGE__->meta->make_immutable;
55 }
56 {
57     package My::Model;
58     use Moose;
59     extends qw/Catalyst::Model/;
60     __PACKAGE__->meta->make_immutable;
61 }
62 {
63     package My::Role;
64     use Moose::Role;
65     sub _some_method_from_role {}
66 }
67 {
68     package My::Other::Role;
69     use Moose::Role;
70     sub _some_method_from_other_role {}
71 }
72 my %generator_config = (
73     name => 'dynamic_component_method',
74     roles => [qw/My::Other::Role/],
75     superclasses => ['My::Other::Superclass'],
76     methods => {
77         my_other_injected_method => sub {},
78     },
79 );
80 my $extra_config = {
81     superclasses => ['My::Model'],
82     roles => ['My::Role'],
83     methods => {
84         my_injected_method => sub { 'quuux' },
85     }
86 };
87 {
88     # Do not specify any resolve strategies, so get defaults:
89     # methods - merge
90     # superclasses - replace
91     # roles - merge
92     my $app_meta = generate_testapp({
93         %generator_config,
94     });
95     my $app = $app_meta->name;
96     $app->dynamic_component_method( "Model::Foo", $extra_config );
97     my $model = $app->model('Foo');
98     isa_ok($model, 'My::Model', 'Correct superclass');
99     ok(!$model->isa('My::Other::Superclass'),
100         'superclass in extra config replaces by default');
101
102     ok $model->can('_some_method_from_role'), 'Has had role applied';
103     ok !My::Model->can('_some_method_from_role'), 'Role applied at right place';
104
105     ok $model->can('_some_method_from_other_role'),
106         'Role application merges by default';
107
108     ok $model->can('my_injected_method'), 'Injected method there as expected';
109     is $model->my_injected_method, 'quuux', 'Injected method returns correct val';
110
111     ok $model->can('my_other_injected_method'),
112         'Injected methods merged by default';
113 }
114 {
115     # Specify resolve strategies, totally opposite the defaults:
116     my $app_meta = generate_testapp({
117         %generator_config,
118         roles_resolve_strategy => 'replace',
119         superclasses_resolve_strategy => 'merge',
120         methods_resolve_strategy => 'replace',
121     });
122     my $app = $app_meta->name;
123     $app->dynamic_component_method( "Model::Foo", $extra_config );
124     my $model = $app->model('Foo');
125     isa_ok($model, 'My::Model', 'Correct superclass');
126     isa_ok($model, 'My::Other::Superclass',
127         'superclasses merged');
128
129     ok $model->can('_some_method_from_role'), 'Has had role applied';
130     ok !My::Model->can('_some_method_from_role'), 'Role applied at right place';
131
132     ok !$model->can('_some_method_from_other_role'),
133         'Role application replaces when configured';
134
135     ok $model->can('my_injected_method'), 'Injected method there as expected';
136     is $model->my_injected_method, 'quuux', 'Injected method returns correct val';
137
138     ok !$model->can('my_other_injected_method'),
139         'Injected methods replaced';
140 }
141 {
142     # Test that replace with blank config doesnt actually replace the config with blank
143     my $app_meta = generate_testapp({
144         %generator_config,
145         roles_resolve_strategy => 'replace',
146         superclasses_resolve_strategy => 'replace',
147         methods_resolve_strategy => 'replace',
148     });
149
150     my $app = $app_meta->name;
151     $app->dynamic_component_method( "Model::Foo", {} );
152     my $model = $app->model('Foo');
153
154     ok $model->can('my_other_injected_method'),
155         'Injected method present';
156
157     ok($model->isa('My::Other::Superclass'),
158         'superclasses not replaced as not set');
159
160     ok $model->can('_some_method_from_other_role'),
161         'Role application does not replace as not set';
162 }
163 {
164     # Test that replace with explicit blanks does so.
165     my $app_meta = generate_testapp({
166         %generator_config,
167         roles_resolve_strategy => 'replace',
168         superclasses_resolve_strategy => 'replace',
169         methods_resolve_strategy => 'replace',
170     });
171
172     my $app = $app_meta->name;
173     $app->dynamic_component_method( "Model::Foo", { superclasses => [], roles => [], methods => {} } );
174     my $model = $app->model('Foo');
175
176     ok !$model->can('my_other_injected_method'),
177         'Injected method not present';
178
179     ok(!$model->isa('My::Other::Superclass'),
180         'superclasses not replaced as set to []');
181
182     ok !$model->can('_some_method_from_other_role'),
183         'Role application replaces as set to []';
184 }
185 {
186     # Test that base strings get listified.
187     my $app_meta = generate_testapp({
188         %generator_config,
189     });
190
191     my $app = $app_meta->name;
192     $app->dynamic_component_method( "Model::Foo", { superclasses => 'My::Model', roles => 'My::Role', } );
193     my $model = $app->model('Foo');
194
195     ok $model->can('my_other_injected_method'),
196         'Injected method present';
197
198     ok(!$model->isa('My::Other::Superclass'),
199         'superclasses replaced');
200
201     ok $model->can('_some_method_from_other_role'),
202         'Role application merges';
203 }
204
205 {
206     # Test that base strings get listified.
207     my $app_meta = generate_testapp({
208         %generator_config,
209         roles => 'My::Other::Role',
210         superclasses => 'My::Other::Superclass',
211     });
212
213     my $app = $app_meta->name;
214     $app->dynamic_component_method( "Model::Foo", { } );
215     my $model = $app->model('Foo');
216
217     ok $model->can('my_other_injected_method'),
218         'Injected method present';
219
220     ok($model->isa('My::Other::Superclass'),
221         'superclasses from string');
222
223     ok $model->can('_some_method_from_other_role'),
224         'Role application merges';
225 }
226