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