confound++
[gitmo/Moose.git] / t / 030_roles / 007_roles_and_required_method_edge_cases.t
CommitLineData
0558683c 1#!/usr/bin/perl
2
3use strict;
4use warnings;
5
e7f8d0c2 6use Test::More tests => 17;
0558683c 7use Test::Exception;
8
1db8ecc7 9=pod
10
11NOTE:
12A fair amount of these tests will likely be irrelevant
13once we have more fine grained control over the class
14building process. A lot of the edge cases tested here
15are actually related to class construction order and
16not any real functionality.
17- SL
18
19=cut
20
0558683c 21BEGIN {
22 use_ok('Moose');
23 use_ok('Moose::Role');
24}
25
26=pod
27
28Role which requires a method implemented
29in another role as an override (it does
30not remove the requirement)
31
32=cut
33
34{
35 package Role::RequireFoo;
36 use strict;
37 use warnings;
38 use Moose::Role;
39
40 requires 'foo';
41
42 package Role::ProvideFoo;
43 use strict;
44 use warnings;
45 use Moose::Role;
46
47 ::lives_ok {
48 with 'Role::RequireFoo';
49 } '... the required "foo" method will not exist yet (but we will live)';
50
51 override 'foo' => sub { 'Role::ProvideFoo::foo' };
52}
53
54is_deeply(
55 [ Role::ProvideFoo->meta->get_required_method_list ],
56 [ 'foo' ],
57 '... foo method is still required for Role::ProvideFoo');
58
59=pod
60
61Role which requires a method implemented
62in the consuming class as an override.
63It will fail since method modifiers are
64second class citizens.
65
66=cut
67
68{
69 package Class::ProvideFoo::Base;
70 use Moose;
71
72 sub foo { 'Class::ProvideFoo::Base::foo' }
73
74 package Class::ProvideFoo::Override1;
75 use Moose;
76
77 extends 'Class::ProvideFoo::Base';
78
1db8ecc7 79 ::lives_ok {
0558683c 80 with 'Role::RequireFoo';
1db8ecc7 81 } '... the required "foo" method will be found in the superclass';
0558683c 82
83 override 'foo' => sub { 'Class::ProvideFoo::foo' };
84
85 package Class::ProvideFoo::Override2;
86 use Moose;
87
88 extends 'Class::ProvideFoo::Base';
89
90 override 'foo' => sub { 'Class::ProvideFoo::foo' };
91
e7f8d0c2 92 ::lives_ok {
0558683c 93 with 'Role::RequireFoo';
e7f8d0c2 94 } '... the required "foo" method exists, although it is overriden locally';
0558683c 95
96}
97
98=pod
99
100Now same thing, but with a before
101method modifier.
102
103=cut
104
105{
106 package Class::ProvideFoo::Before1;
107 use Moose;
108
109 extends 'Class::ProvideFoo::Base';
110
1db8ecc7 111 ::lives_ok {
0558683c 112 with 'Role::RequireFoo';
1db8ecc7 113 } '... the required "foo" method will be found in the superclass';
0558683c 114
115 before 'foo' => sub { 'Class::ProvideFoo::foo:before' };
116
117 package Class::ProvideFoo::Before2;
118 use Moose;
119
120 extends 'Class::ProvideFoo::Base';
121
122 before 'foo' => sub { 'Class::ProvideFoo::foo:before' };
123
e7f8d0c2 124 ::lives_ok {
0558683c 125 with 'Role::RequireFoo';
e7f8d0c2 126 } '... the required "foo" method exists, although it is a before modifier locally';
0558683c 127
128 package Class::ProvideFoo::Before3;
129 use Moose;
130
131 extends 'Class::ProvideFoo::Base';
132
0558683c 133 sub foo { 'Class::ProvideFoo::foo' }
134 before 'foo' => sub { 'Class::ProvideFoo::foo:before' };
135
e7f8d0c2 136 ::lives_ok {
137 with 'Role::RequireFoo';
138 } '... the required "foo" method exists locally, and it is modified locally';
139
0558683c 140 package Class::ProvideFoo::Before4;
141 use Moose;
142
143 extends 'Class::ProvideFoo::Base';
144
145 sub foo { 'Class::ProvideFoo::foo' }
146 before 'foo' => sub { 'Class::ProvideFoo::foo:before' };
147
148 ::isa_ok(__PACKAGE__->meta->get_method('foo'), 'Class::MOP::Method::Wrapped');
149 ::is(__PACKAGE__->meta->get_method('foo')->get_original_method->package_name, __PACKAGE__,
150 '... but the original method is from our package');
151
152 ::lives_ok {
153 with 'Role::RequireFoo';
154 } '... the required "foo" method exists in the symbol table (and we will live)';
e7f8d0c2 155
0558683c 156}
157
158=pod
159
160Now same thing, but with a method from an attribute
161method modifier.
162
163=cut
164
165{
166
167 package Class::ProvideFoo::Attr1;
168 use Moose;
169
170 extends 'Class::ProvideFoo::Base';
171
1db8ecc7 172 ::lives_ok {
0558683c 173 with 'Role::RequireFoo';
1db8ecc7 174 } '... the required "foo" method will be found in the superclass (but then overriden)';
0558683c 175
176 has 'foo' => (is => 'ro');
177
178 package Class::ProvideFoo::Attr2;
179 use Moose;
180
181 extends 'Class::ProvideFoo::Base';
182
183 has 'foo' => (is => 'ro');
184
185 ::dies_ok {
186 with 'Role::RequireFoo';
187 } '... the required "foo" method exists, but it is a before (and we will die)';
188}
825a80de 189
190# ...
191# a method required in a role, but then
192# implemented in the superclass (as an
193# attribute accessor too)
194
195{
196 package Foo::Class::Base;
197 use Moose;
198
199 has 'bar' => (
200 isa => 'Int',
201 is => 'rw',
202 default => sub { 1 }
203 );
204}
205{
206 package Foo::Role;
207 use Moose::Role;
208
209 requires 'bar';
0558683c 210
825a80de 211 has 'foo' => (
212 isa => 'Int',
213 is => 'rw',
214 lazy => 1,
215 default => sub { (shift)->bar + 1 }
216 );
217}
218{
219 package Foo::Class::Child;
220 use Moose;
221 extends 'Foo::Class::Base';
222
223 ::dies_ok {
224 with 'Foo::Role';
225 } '... our role combined successfully';
226}
227
3dd18b73 228# a method required in a role and implemented in a superclass, with a method
229# modifier in the subclass. this should live, but dies in 0.26 -- hdp,
230# 2007-10-11
825a80de 231
3dd18b73 232{
233 package Bar::Class::Base;
234 use Moose;
825a80de 235
3dd18b73 236 sub bar { "hello!" }
237}
238{
239 package Bar::Role;
240 use Moose::Role;
241 requires 'bar';
242}
243{
244 package Bar::Class::Child;
245 use Moose;
246 extends 'Bar::Class::Base';
247 after bar => sub { "o noes" };
4ec69f21 248 # technically we could run lives_ok here, too, but putting it into a
249 # grandchild class makes it more obvious why this matters.
250}
251{
252 package Bar::Class::Grandchild;
253 use Moose;
254 extends 'Bar::Class::Child';
3dd18b73 255 ::lives_ok {
256 with 'Bar::Role';
257 } 'required method exists in superclass as non-modifier, so we live';
258}
e7f8d0c2 259
260{
261 package Bar2::Class::Base;
262 use Moose;
263
264 sub bar { "hello!" }
265}
266{
267 package Bar2::Role;
268 use Moose::Role;
269 requires 'bar';
270}
271{
272 package Bar2::Class::Child;
273 use Moose;
274 extends 'Bar2::Class::Base';
275 override bar => sub { "o noes" };
276 # technically we could run lives_ok here, too, but putting it into a
277 # grandchild class makes it more obvious why this matters.
278}
279{
280 package Bar2::Class::Grandchild;
281 use Moose;
282 extends 'Bar2::Class::Child';
283 ::lives_ok {
284 with 'Bar2::Role';
285 } 'required method exists in superclass as non-modifier, so we live';
286}